/* ═══════════════════════════════════════════════════════════════════════════
   Rava · Editorial — the shared shell for the internal surfaces
   v1.0 · 2026-09-07
   ───────────────────────────────────────────────────────────────────────────
   Kian, 2026-09-07: "go for editorial-warm, adapt Rava's colors on it, and
   apply to panel.rava.capital (with Rava's ivory as background and Ajori and
   our other colors) … while you are in there we need dark/light switch."

   This file does NOT replace rava-carbon.css. Carbon v1.0 stays exactly where
   it is and research.rava.capital keeps serving it — Kian praised that page and
   was not asked about it. This is a second, parallel shell for the panel. Both
   files present the SAME class contract (.r-head, .r-btn, .r-table, .r-tag …)
   and the same --r-* token names, which is why swapping them is a <link> change
   and not a markup rewrite.

   WHAT IS TAKEN FROM better-design.com/design-systems/editorial-warm:
     · the warm cream canvas, here replaced by Rava's own ivory (see below)
     · a real radius scale — pill controls, 16px fields, 24px surfaces — after
       a system that was square everywhere
     · the glass material: translucent warm-white surfaces carrying an inset
       top highlight and a soft, wide, low-opacity outer shadow
     · a serif for display type, self-hosted (see TYPE)
     · mono for labels, small and tracked

   WHAT IS NOT TAKEN, and why:

     · ⚠ THE TERRACOTTA PRIMARY. editorial-warm's --primary is
       oklch(0.50 0.115 38) — which is, to within a rounding error, ajori
       #A54324. The system therefore wants ajori to be the ACTION colour: its
       links, its focus ring, its filled button. That collides head-on with a
       standing ruling. Kian, 2026-09-06: "convert al C2A to Lajvard" — ajori is
       identity ONLY, lajvard #2A4A6B is action ONLY. Asked again on 2026-09-07
       he chose to keep that ruling. So editorial-warm's action role is remapped
       onto lajvard and ajori is left holding identity, exactly as in Carbon.
       This is the single largest divergence from the published system, and it
       is deliberate. ⚠ lajvard still sits under `retired_blue` in tokens.json
       v5.1; this is the second stylesheet to depend on a scoped restoration
       that has never been written into the palette block.

     · ⚠ THE BACKDROP BLUR, almost everywhere. editorial-warm specifies
       backdrop-filter: blur(28px) saturate(160%) on buttons, fields and cards.
       That reads as glass because the published system sits on a textured
       canvas. This panel's ground is FLAT ivory — blurring a flat colour
       returns the same flat colour, so the filter would buy nothing visible and
       cost a compositing layer on every scroll of a 200-row table. The blur is
       therefore kept in exactly one place, `.r-head`, which is sticky and does
       have content moving underneath it. Everything else keeps the glass
       RESULT — translucency, inset highlight, soft shadow — without the filter.

     · THE FRAUNCES/INTER/JETBRAINS STACK as published, fetched from Google.
       Zero foreign hosts is doctrine here: during an isolation window a
       colleague in Tehran reaches this server perfectly well and Google not at
       all. Fraunces is self-hosted instead (see TYPE) and the body faces stay
       Abar and IBM Plex.

     · A DARK MODE — because editorial-warm does not have one. Its published
       `.dark` block is byte-identical to its `:root` block: same background,
       same foreground, same primary, all 34 tokens. Asking it for a dark theme
       returns the light theme. Kian asked for a dark/light switch, so the dark
       half below is AUTHORED, from Rava's own ink and earth tiers, and every
       pair in it was measured rather than eyeballed — see the ⚠ on the ramp.

   ⚠ LOAD ORDER, unchanged from Carbon: where Pico is present (the panel) this
   file loads AFTER pico.min.css and is retuned through --pico-* variables in
   the app sheet rather than fought with !important.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1 · type ────────────────────────────────────────────────────────────────
   Kian, 2026-09-07: "farsi is Abar mid to high contrast."

   That is the pairing that makes this work. editorial-warm's voice is a
   high-contrast serif; Persian has no Fraunces, but Abar has a CNTR axis, and
   Abar at CNTR 100 is a high-contrast face in the same sense. So the two
   scripts are not given two different personalities — they are given the same
   move on their own terms:

     Farsi   body     Abar  CNTR 40  (Mid)     ─┐ one file, one axis
     Farsi   display  Abar  CNTR 100 (High)    ─┘
     Latin   body     IBM Plex Sans
     Latin   display  Fraunces (opsz/wght VF)
     machine anything IBM Plex Mono

   ⚠ ONE VARIABLE FILE, not five statics. AbarFaNum-VF.woff2 is 140 KB and
   carries wght 100–950 × CNTR 0–100 — all 30 named instances. The five static
   Abar faces Carbon ships total 219 KB and cover three of them. They are still
   on disk because rava-carbon.css still refers to them; nothing here does.

   ⚠ THE wght DEFAULT ON THIS FONT IS 100, NOT 400. Abar's fvar declares
   wght min=100 default=100 max=950. If the wght axis is ever left unmapped the
   whole panel renders Thin — a loud, obvious failure rather than a subtle one,
   which is the only good thing about it. font-weight drives wght; CNTR is set
   through font-variation-settings and is the ONLY axis named there, so
   font-weight keeps working normally.

   ⚠ Fraunces is the LATIN SUBSET only (U+0000-00FF …), 67 KB, taken from
   Google on the Mac and served from our own /fonts. The server never fetches
   it. It is never given the Arabic range — a face without Persian glyphs that
   claims the range silently drops the page to a fallback. */
@font-face{font-family:"Abar";src:url("fonts/AbarFaNum-VF.woff2") format("woff2");
  font-weight:100 950;font-style:normal;font-display:swap}
@font-face{font-family:"Fraunces";src:url("fonts/Fraunces-var.woff2") format("woff2");
  font-weight:400 700;font-style:normal;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,
                U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Plex";src:url("fonts/IBMPlexSans-var.woff2") format("woff2");
  font-weight:100 700;font-style:normal;font-display:swap}
@font-face{font-family:"Plex Mono";src:url("fonts/IBMPlexMono-Regular.woff2") format("woff2");
  font-weight:400;font-style:normal;font-display:swap}
@font-face{font-family:"Plex Mono";src:url("fonts/IBMPlexMono-Medium.woff2") format("woff2");
  font-weight:500;font-style:normal;font-display:swap}

/* ── 2 · tokens ──────────────────────────────────────────────────────────────
   ⚠ THE DARK VALUES ARE DECLARED ONCE, HERE, as --d-*. The two blocks in §3
   only ASSIGN them. This is not stylistic: a dark theme has to be applied from
   two different selectors (a media query for "follow the system" and an
   attribute for "the user chose"), and writing the palette out twice is exactly
   how one scheme ends up a shade behind the other after an edit. Values live
   once; only the mapping is repeated, and sync-shared.sh asserts the two
   mappings are identical. */
:root{
  /* ── the ground. SOURCE: `02 Visual Identity/Color System/Final Palette/
     Rava - Final Palette_V05.ase`, handed over 2026-09-08 and parsed from the
     binary, not eyeballed. Seven swatches, and they are the authority here.

     ⚠ THE GROUND IS CREAM #F8ECEA, NOT IVORY #FFF8EC. v1.0 of this file shipped
     ivory on the strength of tokens.json v5.1 and Kian's word "ivory". V05
     names its ground CREAM and it is a different colour: ivory leans YELLOW
     (B 236 well under R 255), cream leans PINK (B 234 ≈ G 236). Every neutral
     below was re-derived to follow cream's lean — an ivory-derived grey on a
     cream ground reads as a stain, which is the whole reason they were redone
     rather than kept.

     ⚠ tokens.json v5.1 is now BEHIND V05 in three ways and has not been
     rewritten: V05 has no "ivory", its "Sand" is tokens.json's *wheat*
     (#E3CDB6 — tokens.json's own sand is #D5B98A), and it carries TWO BLUES
     that tokens.json files under `retired_blue`. Recorded, not resolved. */
  --r-bg:#F8ECEA;          /* Cream  — V05, the page ground */
  --r-raise:#FDF9F8;       /* the surface a row or a card sits on */
  --r-layer:#F3E6E3;       /* a surface ON the ground: table head, field, chip */
  --r-hover:#EFDEDA;
  --r-line:#E7D6D2;        /* the hairline */
  --r-line-2:#D9C3BD;      /* where two surfaces of equal value meet */

  /* ── text. ⚠ Every tier clears 4.5:1 on ALL FOUR surfaces above, worst case,
     not just on the page ground. Measured against V05, not carried over:
       t1 12.83  ·  t2 5.31  ·  t3 4.63
     ⚠ --r-hover is deliberately LIGHTER than v1.0's was. At the heavier tint
     the third tier could not clear 4.5 without collapsing into the second, so
     the surface moved rather than the text — three legible tiers beat a pretty
     hover. */
  --r-t1:#3B0E12;          /* Maroon — V05. The ink is a palette colour now,
                              not a neutral chosen to sit near one. */
  --r-t2:#6B5550;
  --r-t3:#775D57;

  /* ── identity. Rust and nothing else. */
  --r-ajori:#A54323;       /* Rust — V05. Was #A54324; V05's float is 0.137,
                              which rounds to 35 not 36. One step of blue. */
  --r-ajori-ink:#F8ECEA;

  /* ── action. ⚠ NAVY, AND THIS REPLACES LAJVARD.
     Kian's ruling on 2026-09-07 was about ROLES — blue acts, ajori identifies —
     and it stands untouched. What changed is which blue: lajvard #2A4A6B is
     NOT in V05, so shipping it meant shipping an off-palette colour into the
     one job the palette cares most about. V05's blues are Navy #030F24 and
     Blue #81A9D3, so the role is filled from the master.

     ⚠ Navy is very dark — as a pill it reads near-black rather than blue. That
     is correct for this system, not a compromise: the warm-editorial family
     puts a flat near-black pill on a cream ground, and 16.56:1 with cream ink
     is the strongest action contrast this panel has ever had. */
  --r-act:#030F24;         /* Navy — V05 */
  --r-act-hover:#12233F;
  --r-act-line:#030F24;
  --r-act-ink:#F8ECEA;
  --r-act-text:#030F24;

  --r-danger:#8A2020;
  --r-danger-ink:#FFFFFF;

  /* ── the rest of V05. ⚠ NONE of these carries text on cream: Sand 1.33:1,
     Blue 2.13:1, Brown 3.63:1 (large only). Fill, tint and border work only.
     Blue is the palette's visible blue and it CANNOT be a light-mode CTA for
     exactly this reason — it appears as a fill with navy text on it (7.79:1),
     and it becomes the action colour in dark, where the grounds invert. */
  --r-sand:#E3CDB6;        /* Sand  — V05 */
  --r-brown:#A0724C;       /* Brown — V05 */
  --r-blue:#81A9D3;        /* Blue  — V05 */
  --r-maroon:#3B0E12;      /* Maroon — V05, also the ink */

  /* ── the dark palette, declared once. Assigned in §3. ─────────────────────
     ⚠ THE DARK GROUND IS V05's NAVY. It is not a tint of the light theme and
     it is not invented: the palette already contains a near-black blue, so the
     dark theme is built on a palette colour rather than on a charcoal chosen to
     go with one. v1.0's warm charcoal #1F1A16 is gone.

     ⚠ THE ACTION COLOUR INVERTS. On cream the action is the DARK blue; on navy
     it has to be the LIGHT one, or the button disappears into its own ground.
     That is why --d-act-ink exists and is Navy: the dark pill is a light-blue
     fill, and cream ink on it would be 1.3:1 — invisible. v1.0 had no
     --*-act-ink in the dark mapping because its dark fill happened to stay
     dark. Do not remove it. */
  --d-bg:#030F24;  --d-raise:#111C30; --d-layer:#1B2639; --d-hover:#263143;
  --d-line:#22304A; --d-line-2:#33425E;
  --d-t1:#F8ECEA;  --d-t2:#E3CDB6;    --d-t3:#AD988E;
  --d-ajori:#E89070;       /* Rust at its V05 value is 2.14:1 on navy — unusable.
                              Lifted until it clears 4.5 on every dark surface. */
  --d-ajori-ink:#030F24;
  --d-act:#81A9D3; --d-act-hover:#9BBCDF; --d-act-line:#81A9D3; --d-act-text:#81A9D3;
  --d-act-ink:#030F24;
  --d-danger:#EE908A;
  --d-glass:rgba(248,236,234,.05);
  --d-glass-strong:rgba(248,236,234,.09);
  --d-highlight:rgba(248,236,234,.10);
  --d-head-bg:rgba(3,15,36,.82);

  /* ── geometry. editorial-warm's radius scale, which is the loudest single
     difference from Carbon: that system was square EVERYWHERE by ruling, this
     one is not square anywhere. */
  --r-radius:16px;         /* fields, chips, the default */
  --r-radius-sm:10px;
  --r-radius-lg:24px;      /* cards, the table box, any real surface */
  --r-pill:999px;          /* every button. editorial-warm's own choice. */
  --r-head:56px;           /* ⚠ 48 in Carbon. See §5. */
  --r-pad:16px;
  --r-max:1100px;

  /* ── the glass material, minus the blur. See the ⚠ in the header. */
  --r-glass:rgba(255,255,255,.55);
  --r-glass-strong:rgba(255,255,255,.75);
  --r-highlight:rgba(255,255,255,.75);
  --r-head-bg:rgba(255,248,236,.82);
  --r-shadow:inset 0 1.5px 0 var(--r-highlight),
             0 1px 3px rgba(59,14,18,.05), 0 2px 8px rgba(59,14,18,.06);
  --r-shadow-lift:inset 0 1.5px 0 var(--r-highlight),
             0 2px 5px rgba(59,14,18,.06), 0 6px 16px rgba(59,14,18,.09);

  --r-fa:"Abar",Tahoma,system-ui,sans-serif;
  --r-en:"Plex",system-ui,-apple-system,"Segoe UI",sans-serif;
  --r-serif:"Fraunces",ui-serif,Georgia,"Times New Roman",serif;
  --r-mono:"Plex Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  /* the two contrast cuts of Abar, as settings rather than as families */
  --r-cntr-body:"CNTR" 40;    /* Mid  */
  --r-cntr-display:"CNTR" 100;/* High */
}

/* ── 3 · dark ────────────────────────────────────────────────────────────────
   Two selectors, one palette, because there are two ways to be in dark mode.

   ⚠ THE `:not([data-theme=light])` IS LOAD-BEARING. Without it, a reader whose
   OS is dark but who has explicitly chosen light in the header switch gets the
   dark palette anyway, and the switch appears broken in exactly one
   configuration — the one nobody tests on.

   ⚠ SPECIFICITY, and this is the bug Stage 28 shipped. Pico's dark theme lives
   at `:root:not([data-theme])` — a two-class selector — and its explicit dark
   at `[data-theme=dark]`. These blocks are (0,2,0) and (0,2,0) and this file
   loads after Pico, so they carry. The --pico-* bridge in the APP sheet is the
   half that has to sit on `:root:root`; see rava-editorial-panel.css §1.

   ⚠ The explicit block comes LAST on purpose: when the OS is dark and the
   reader has chosen dark, both match at equal specificity and source order
   decides. Do not reorder these two. */
@media (prefers-color-scheme:dark){
  :root:not([data-theme=light]){
    --r-bg:var(--d-bg); --r-raise:var(--d-raise); --r-layer:var(--d-layer);
    --r-hover:var(--d-hover); --r-line:var(--d-line); --r-line-2:var(--d-line-2);
    --r-t1:var(--d-t1); --r-t2:var(--d-t2); --r-t3:var(--d-t3);
    --r-ajori:var(--d-ajori); --r-ajori-ink:var(--d-ajori-ink);
    --r-act:var(--d-act); --r-act-hover:var(--d-act-hover);
    --r-act-line:var(--d-act-line); --r-act-text:var(--d-act-text);
    --r-act-ink:var(--d-act-ink);
    --r-danger:var(--d-danger);
    --r-glass:var(--d-glass); --r-glass-strong:var(--d-glass-strong);
    --r-highlight:var(--d-highlight); --r-head-bg:var(--d-head-bg);
    color-scheme:dark;
  }
}
:root[data-theme=dark]{
  --r-bg:var(--d-bg); --r-raise:var(--d-raise); --r-layer:var(--d-layer);
  --r-hover:var(--d-hover); --r-line:var(--d-line); --r-line-2:var(--d-line-2);
  --r-t1:var(--d-t1); --r-t2:var(--d-t2); --r-t3:var(--d-t3);
  --r-ajori:var(--d-ajori); --r-ajori-ink:var(--d-ajori-ink);
  --r-act:var(--d-act); --r-act-hover:var(--d-act-hover);
  --r-act-line:var(--d-act-line); --r-act-text:var(--d-act-text);
  --r-act-ink:var(--d-act-ink);
  --r-danger:var(--d-danger);
  --r-glass:var(--d-glass); --r-glass-strong:var(--d-glass-strong);
  --r-highlight:var(--d-highlight); --r-head-bg:var(--d-head-bg);
  color-scheme:dark;
}
:root[data-theme=light]{color-scheme:light}

/* ── 4 · the ground ──────────────────────────────────────────────────────── */
*{box-sizing:border-box}
html,body{margin:0;min-height:100%}
body{
  background:var(--r-bg);color:var(--r-t1);
  font-family:var(--r-fa);font-variation-settings:var(--r-cntr-body);
  font-size:15px;line-height:1.75;
  -webkit-font-smoothing:antialiased;
}
/* ⚠ Tracking is applied to the ENGLISH side only. Letter-spacing inserts space
   between letters the Persian script JOINS, so a tracked Farsi word visibly
   comes apart. Carried straight over from Carbon; it was right there too. */
html[lang=en] body{font-family:var(--r-en);font-variation-settings:normal;
  font-size:14px;line-height:1.55;letter-spacing:.01em}

/* ── 5 · anything a machine reads back ───────────────────────────────────────
   ⚠ Abar FaNum draws digits as PERSIAN numerals — right in Farsi prose, wrong
   for a uid, a port, a size or a hex. Mono AND an explicit ltr isolate, or
   "8773" and "uid=info" come back reordered inside the RTL run. */
.mono,code,kbd,samp{font-family:var(--r-mono);font-variation-settings:normal;
  font-size:.86em;letter-spacing:0;direction:ltr;unicode-bidi:isolate;
  font-variant-numeric:tabular-nums}

/* ── 6 · the header ──────────────────────────────────────────────────────────
   ⚠ THE CELL STRUCTURE IS KEPT, and that is a decision, not an oversight.
   editorial-warm has no header doctrine; Carbon's row of full-height cells
   divided by hairlines is the thing Kian named as beautiful, and the 3px rule
   marking the current page is a NON-COLOUR signal that a colour-blind reader
   and a monochrome print both survive. Replacing it with a soft pill would have
   thrown that away for nothing. So the structure is Carbon's and the MATERIAL
   is editorial-warm's: taller, translucent, blurred, hairlines softened.

   ⚠ 56px, not Carbon's 48. The radius scale needs the room — a pill button and
   a 16px field inside a 48px bar leave 4px of air above and below and the bar
   reads as cramped. Every child is still full height and its own hit target.

   ⚠ padding:0 is the whole trick, not a reset. Pico styles a bare <header> with
   1rem of block padding; with box-sizing:border-box that leaves a 24px content
   box inside the 56px bar, so every divider runs a fraction of the height. This
   shipped once, at 15px in a 48px bar, and looked roughly right in a screenshot.
   Measure it with getBoundingClientRect; do not judge it by eye. */
.r-head{
  height:var(--r-head);display:flex;align-items:stretch;
  background:var(--r-head-bg);
  /* the one place the blur is real: content scrolls underneath this */
  -webkit-backdrop-filter:blur(20px) saturate(150%);
  backdrop-filter:blur(20px) saturate(150%);
  border-bottom:1px solid var(--r-line);
  position:sticky;top:0;z-index:20;
  padding:0;margin:0;
}
.r-head a{color:inherit;text-decoration:none}

.r-brand{
  display:flex;align-items:center;gap:10px;padding:0 var(--r-pad);
  border-inline-end:1px solid var(--r-line);
  font-family:var(--r-fa);font-variation-settings:var(--r-cntr-display);
  font-weight:600;font-size:16px;letter-spacing:0;
  white-space:nowrap;color:var(--r-t1);
}
html[lang=en] .r-brand{font-family:var(--r-serif);font-variation-settings:normal;
  font-weight:600;font-size:16px;letter-spacing:-.01em}
/* the mark. ⚠ Drawn, never the character "]" — a bracket glyph is mirrored by
   the bidi algorithm inside an RTL run, so a typed one turns around and faces
   away from the words it is meant to hold. Per Bracket Grammar, in Farsi the
   opening bracket sits on the RIGHT. */
.r-mark{height:22px;width:auto;color:var(--r-ajori);flex:none;display:block}
.r-brand em{font-style:normal;color:var(--r-t2);font-weight:400}
.r-brand em::before{content:"\00a0·\00a0"}

.r-nav{display:flex;align-items:stretch;min-width:0;overflow-x:auto;scrollbar-width:none}
.r-nav::-webkit-scrollbar{display:none}
.r-nav a{
  display:flex;align-items:center;padding:0 var(--r-pad);
  color:var(--r-t2);font-size:14.5px;white-space:nowrap;
  border-inline-end:1px solid var(--r-line);
  box-shadow:inset 0 3px 0 transparent;
  transition:background .14s ease,color .14s ease;
}
html[lang=en] .r-nav a{font-size:13.5px;letter-spacing:.01em}
.r-nav a[aria-current=page]{
  color:var(--r-t1);font-variation-settings:var(--r-cntr-display);font-weight:600;
  background:var(--r-glass);
  box-shadow:inset 0 3px 0 var(--r-ajori);
}
html[lang=en] .r-nav a[aria-current=page]{font-family:var(--r-en);
  font-variation-settings:normal;font-weight:600}

.r-gap{flex:1;min-width:8px}

.r-meta{display:flex;align-items:stretch;font-size:13px}
.r-meta > *{
  display:flex;align-items:center;padding:0 var(--r-pad);
  border-inline-start:1px solid var(--r-line);color:var(--r-t2);white-space:nowrap;
}
.r-meta .r-lang{font-family:var(--r-mono);font-variation-settings:normal;
  font-size:12px;letter-spacing:.03em}

/* ── 7 · the theme switch ────────────────────────────────────────────────────
   Kian, 2026-09-07: "while you are in there we need dark/light switch."

   THREE states, not two: light · dark · auto. Auto is the default and it is
   what a first-time reader gets, so the panel follows the OS until somebody
   says otherwise — and "otherwise" has to be reachable from either end, which
   a two-state toggle cannot do once it has been touched.

   ⚠ It is a <button> that cycles, not a checkbox, because the state is ternary
   and there is no native ternary control. aria-label carries the CURRENT state
   and the button's text carries it visibly too, so the state is never colour or
   icon alone. The panel writes the choice to a cookie and renders data-theme on
   <html> server-side, which is why there is no flash of the wrong theme on a
   reload — see panel_v2.py head_tags(). */
/* ⚠ NOT display:contents, and that was measured the hard way. With the form
   at display:contents the button becomes the flex item, and Chrome then
   refuses to stretch it: align-self computed `stretch` and the used height
   stayed 40px in a 56px bar, so the divider ran three quarters of the cell.
   Instead the FORM is the cell — it stretches like any block, it collects the
   hairline from `.r-meta > *`, and it hands its padding to the button so the
   whole cell is the hit target rather than a 40px island inside it. */
.r-themef{display:flex;align-items:stretch}
.r-meta > .r-themef{padding:0}
.r-theme{
  display:flex;align-items:center;gap:7px;padding:0 var(--r-pad);
  border:0;background:transparent;color:var(--r-t2);
  font:inherit;font-size:12px;font-family:var(--r-mono);
  font-variation-settings:normal;letter-spacing:.03em;
  cursor:pointer;white-space:nowrap;
  transition:background .14s ease,color .14s ease;
}
.r-theme svg{width:15px;height:15px;flex:none;display:block}
/* only the glyph for the ACTIVE state is shown; the other two are hidden with
   [hidden]-equivalent semantics rather than opacity, so a screen reader that
   walks the button does not read three icon names */
.r-theme .i-auto,.r-theme .i-sun,.r-theme .i-moon{display:none}
:root:not([data-theme]) .r-theme .i-auto{display:block}
:root[data-theme=light] .r-theme .i-sun{display:block}
:root[data-theme=dark]  .r-theme .i-moon{display:block}
.r-theme:focus-visible{outline:2px solid var(--r-act-text);outline-offset:-3px}
/* ⚠ MEASURED, NOT ASSUMED. Inside the header this button came out 40px tall in
   a 56px bar — every anchor cell beside it stretched to 55 and the button did
   not, so its hairline divider ran three quarters of the height and the header
   went back to being items floating in a bar. A <button> does not stretch as a
   flex item the way the <a> cells do; min-height:40px then wins as its used
   height. align-self has to be stated. This is the same defect class Stage 28
   shipped at 15px in a 48px bar — a screenshot showed nothing either time.
   ⚠ Scoped to .r-head: on the sign-in page the button is NOT in the cell
   grammar and must keep its own 40px touch target. */
.r-head .r-theme{height:100%}

/* ── 8 · the body ────────────────────────────────────────────────────────────
   ⚠ THE DISPLAY FACE IS SPLIT BY SCRIPT AND THAT IS THE POINT. Latin headings
   take Fraunces; Farsi headings take Abar at CNTR 100. They are not the same
   drawing, but they are the same GESTURE — high stroke contrast, an editorial
   voice — which is what keeps an RTL page and an LTR page reading as one
   system instead of two sites. */
.r-main{max-width:var(--r-max);margin:0 auto;padding:32px var(--r-pad) 64px}
h1,h2,h3,h4{font-family:var(--r-fa);font-variation-settings:var(--r-cntr-display);
  font-weight:600;letter-spacing:0;line-height:1.4;color:var(--r-t1)}
html[lang=en] :is(h1,h2,h3,h4){font-family:var(--r-serif);
  font-variation-settings:normal;font-weight:600;letter-spacing:-.015em}
.r-main > h1,.r-main > hgroup > h1{font-size:27px;margin:0 0 4px}
h2{font-size:21px;margin:0 0 3px}
h3{font-size:17px}
.r-sub{color:var(--r-t3);font-size:13px;margin:0 0 24px}
html[lang=en] .r-sub{font-family:var(--r-mono);font-variation-settings:normal;
  font-size:12px;letter-spacing:.03em}

/* ── 9 · buttons ─────────────────────────────────────────────────────────────
   Three, and only three, unchanged from Carbon — a page that needs a fourth is
   a page that has not decided what it wants the reader to do. What changes is
   the shape: editorial-warm makes every button a PILL, and the primary carries
   the glass inset highlight over its fill rather than sitting flat.

     .r-btn         the action. Lajvard, pill, ivory text.
     .r-btn.ghost   a real but secondary action — outline, no fill.
     .r-btn.danger  quiet until hovered, then unmistakable.

   ⚠ 40px minimum height and a 2px focus ring at 2px offset are not stylistic.
   Below 40 the controls in a dense table stop being reliable targets on a
   phone. The offset matters more here than it did on square edges: a ring drawn
   flush to a pill reads as part of the pill. */
.r-btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.45em;
  min-height:40px;padding:0 18px;
  font-family:var(--r-fa);font-variation-settings:var(--r-cntr-display);
  font-weight:600;font-size:14px;line-height:1;
  border-radius:var(--r-pill);cursor:pointer;
  background:var(--r-act);border:1px solid var(--r-act-line);color:var(--r-act-ink);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.22),0 1px 2px rgba(59,14,18,.10);
  transition:background .14s ease,border-color .14s ease,color .14s ease,
             box-shadow .14s ease;
}
html[lang=en] .r-btn{font-family:var(--r-en);font-variation-settings:normal;
  letter-spacing:.01em}
.r-btn:focus-visible{outline:2px solid var(--r-act-text);outline-offset:2px}
.r-btn[disabled],.r-btn[aria-disabled=true]{opacity:.45;cursor:not-allowed}

.r-btn.ghost{background:transparent;border-color:var(--r-act-line);
  color:var(--r-act-text);box-shadow:none}
.r-btn.quiet{background:var(--r-glass);border-color:var(--r-line-2);
  color:var(--r-t2);box-shadow:none}
.r-btn.danger{background:transparent;border-color:var(--r-line-2);
  color:var(--r-t2);box-shadow:none}
.r-btn.sm{min-height:32px;padding:0 13px;font-size:13px}

/* ⚠ Hover lives inside (hover:hover) and (pointer:fine). On a touch screen a
   :hover rule sticks after the tap and leaves a row looking selected when it is
   not — and editorial-warm's own review rules require the guard. */
@media (hover:hover) and (pointer:fine){
  .r-head a:hover{background:var(--r-glass);color:var(--r-t1)}
  .r-theme:hover{background:var(--r-glass);color:var(--r-t1)}
  .r-btn:hover:not([disabled]){background:var(--r-act-hover);
    border-color:var(--r-act-hover);color:var(--r-act-ink);
    box-shadow:inset 0 1.5px 0 rgba(255,255,255,.26),0 2px 6px rgba(59,14,18,.14)}
  .r-btn.ghost:hover{background:var(--r-act);border-color:var(--r-act);
    color:var(--r-act-ink)}
  .r-btn.quiet:hover{background:var(--r-hover);border-color:var(--r-t3);
    color:var(--r-t1)}
  .r-btn.danger:hover{background:var(--r-danger);border-color:var(--r-danger);
    color:var(--r-danger-ink)}
}

/* ── 10 · table ──────────────────────────────────────────────────────────────
   Carbon's data table kept its structure and loses its square box: the wrapper
   is now a 24px card carrying the glass shadow, and the corners clip the first
   and last rows. Everything else — one row rhythm, every column locked to one
   edge, the wrapper scrolling instead of the page — is unchanged, because none
   of it was a Carbon idea, it is just how a dense table works.

   ⚠ border-collapse:separate, not collapse. A collapsed table paints its cell
   borders OUTSIDE the wrapper's border-box, so the top row's rule cuts straight
   across the 24px corner and the card reads as a square box with rounded
   decoration stuck on it. Separate + border-spacing:0 keeps the rules inside
   the clip. This is the single thing that breaks if the radius is ever raised
   without re-checking. */
/* ⚠ overflow-x:auto, NOT overflow:hidden — and this cost a squeezed table.
   The radius needs the wrapper to clip, and `overflow:hidden` clips, so it
   looked correct. But it also REMOVED the horizontal scroll this table has
   always had, so at 800px the columns stopped scrolling and started
   compressing: names and addresses collapsed to one character per line while
   the action cell kept its 11rem select. Setting overflow-x:auto computes
   overflow-y to auto as well, so the corners still clip — the scroll container
   clips to its padding box, which respects border-radius. Clipping and
   scrolling are the same declaration here; do not split them again. */
.r-box{border:1px solid var(--r-line);border-radius:var(--r-radius-lg);
  overflow-x:auto;background:var(--r-raise);box-shadow:var(--r-shadow)}
.r-table{width:100%;border-collapse:separate;border-spacing:0;margin:0;font-size:14px}
html[lang=en] .r-table{font-size:13px}
.r-table thead th{
  background:var(--r-layer);color:var(--r-t2);
  font-family:var(--r-mono);font-variation-settings:normal;
  font-weight:500;font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  text-align:start;white-space:nowrap;
  padding:12px var(--r-pad);border-bottom:1px solid var(--r-line);
}
/* ⚠ Farsi inside a header cell cannot be uppercased or tracked, and Abar is the
   only face here with the glyphs — so the FA side keeps Abar and drops both. */
html[lang=fa] .r-table thead th{font-family:var(--r-fa);
  font-variation-settings:var(--r-cntr-display);font-weight:600;
  font-size:12.5px;letter-spacing:0;text-transform:none}
.r-table :is(td,tbody th){
  padding:11px var(--r-pad);text-align:start;vertical-align:middle;
  border-bottom:1px solid var(--r-line);background:var(--r-raise);
  font-weight:400;
}
.r-table tbody tr:last-child :is(td,th){border-bottom:0}
.r-table td.num,.r-table th.num{font-family:var(--r-mono);font-variation-settings:normal;
  font-size:12px;color:var(--r-t3);white-space:nowrap;width:1%;letter-spacing:0;
  direction:ltr;unicode-bidi:isolate}
@media (hover:hover) and (pointer:fine){
  .r-table tbody tr:hover :is(td,th){background:var(--r-hover)}
}

/* ── 11 · small parts ────────────────────────────────────────────────────────
   A tag is a FACT about a row, never a button — so it does not get the pill
   that every button here has. editorial-warm makes its badges pills; that would
   make a fact indistinguishable from an action at a glance, which is the one
   thing the two-accent ruling exists to prevent. Tags take the field radius. */
.r-tag{display:inline-flex;align-items:center;gap:.3em;
  font-family:var(--r-mono);font-variation-settings:normal;
  font-size:10.5px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--r-t2);background:var(--r-layer);border:1px solid var(--r-line);
  padding:3px 9px;border-radius:var(--r-radius-sm);white-space:nowrap}
.r-tag.key{background:var(--r-ajori);border-color:var(--r-ajori);color:var(--r-ajori-ink)}
.r-tag.soft{background:transparent;border-color:var(--r-ajori);color:var(--r-ajori)}
.r-tag.warn{background:transparent;border-color:var(--r-danger);color:var(--r-danger)}
html[lang=fa] .r-tag{font-family:var(--r-fa);font-variation-settings:var(--r-cntr-body);
  text-transform:none;letter-spacing:0;font-size:12px}

/* a message is a line with a coloured edge, not a coloured box — it can carry a
   generated password and must stay readable, not decorative */
.r-note{border:1px solid var(--r-line);border-radius:var(--r-radius);
  background:var(--r-raise);box-shadow:var(--r-shadow);
  padding:13px var(--r-pad);font-size:14px;margin:0 0 20px}
.r-note.soft{border-inline-start:3px solid var(--r-act-text)}
.r-note.warn{border-inline-start:3px solid var(--r-danger)}

.r-empty{padding:48px var(--r-pad);color:var(--r-t3);text-align:center;
  background:var(--r-layer);line-height:1.85}

.r-help{margin-top:36px;padding:var(--r-pad);border:1px solid var(--r-line);
  border-radius:var(--r-radius-lg);background:var(--r-glass);
  color:var(--r-t3);font-size:13.5px;line-height:1.9;max-width:660px}
.r-help b{color:var(--r-t2);font-weight:600}

.r-foot{max-width:var(--r-max);margin:0 auto;padding:20px var(--r-pad) 44px;
  border-top:1px solid var(--r-line);color:var(--r-t3);font-size:13px}

.r-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ── 12 · motion ─────────────────────────────────────────────────────────────
   ⚠ Everything above transitions colour only — never position, never size. A
   control that moves on hover is a control that moves out from under a shaking
   hand. And the whole lot is switched off for anyone who asked for less. */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{transition-duration:.01ms!important;
    animation-duration:.01ms!important;animation-iteration-count:1!important}
}

/* ── 13 · phone ──────────────────────────────────────────────────────────────
   The header does not collapse into a menu. It keeps its cells and scrolls —
   three destinations do not earn a hamburger, and a scrolling row of cells
   stays honest about how many there are.
   ⚠ The theme switch keeps its glyph and drops its WORD, not the other way
   round: the glyph alone still has its aria-label, the word alone would eat the
   width the nav needs. */
@media (max-width:640px){
  :root{--r-pad:13px;--r-radius-lg:18px}
  .r-head{position:static}
  .r-brand em{display:none}
  .r-meta .r-who{display:none}
  .r-theme span{display:none}
  .r-theme{padding:0 12px}
  .r-main{padding-top:22px}
  .r-main > h1,.r-main > hgroup > h1{font-size:23px}
}
