/* Generated by scripts/build-standalone-css.mjs. Do not edit. */
@font-face{font-family:"Geist";font-style:normal;font-weight:400;font-display:swap;src:url("./fonts/Geist-Regular.woff2") format("woff2")}
@font-face{font-family:"Geist";font-style:normal;font-weight:500;font-display:swap;src:url("./fonts/Geist-Medium.woff2") format("woff2")}
@font-face{font-family:"Geist Mono";font-style:normal;font-weight:400;font-display:swap;src:url("./fonts/GeistMono-Regular.woff2") format("woff2")}
/* Variables only — safe to link inside somebody else's application.
 *
 * Everything here declares custom properties or @font-face and nothing else,
 * so linking it cannot restyle a single element of the host. That matters
 * because the account and credits panels are embedded surfaces: they render
 * inside an app that already has its own design, and a token layer that also
 * reset `body`, `a` and `h1..h6` would silently redesign the host around
 * them.
 *
 * The two class rules that do exist — `.oa-dark` and `.oa-auto` — only
 * re-point variables, and only on the element they are placed on.
 *
 * Use this when embedding. Use ./styles.css for surfaces OpenApps owns.
 */
/* fonts.css deliberately NOT imported -- see scripts/vendor-openapps.sh.
 * It declares every Geist cut; src/fonts.css already declares the three
 * faces this app renders, so importing it would ship them twice. */
/* OpenApps color system.
   Layer 1 — the brand palette, verbatim from the supplied brand CSS (hex values unchanged).
   Layer 2 — ramps derived from those hues with color-mix (no new hues invented).
   Layer 3 — semantic aliases. Product code should only ever use layer 3. */
:root{
  /* ---- 1. Brand palette (verbatim) ---- */
  --black:#000000;
  --white:#ffffff;
  --blue:#15b9eb;
  --green:#00c896;
  --red:#ff4d4d;
  --yellow:#f2e863;
  --orange:#ff8c42;
  --violet:#8c6cff;
  --gray-050:#f8f8f7;
  --gray-100:#f0f0ee;
  --gray-200:#deded9;
  --gray-300:#c1c0b8;
  --gray-400:#989898;
  --gray-500:#7c7c7c;
  --gray-600:#656565;
  --gray-700:#464646;
  --gray-800:#3d3d3d;
  --gray-900:#282828;
  --gray-950:#1a1a1a;

  --white-90:rgba(255,255,255,0.9);
  --white-80:rgba(255,255,255,0.8);
  --white-70:rgba(255,255,255,0.7);
  --white-60:rgba(255,255,255,0.6);
  --white-50:rgba(255,255,255,0.5);
  --white-40:rgba(255,255,255,0.4);
  --white-30:rgba(255,255,255,0.3);
  --white-20:rgba(255,255,255,0.2);
  --white-10:rgba(255,255,255,0.1);
  --white-04:rgba(255,255,255,0.04);
  --white-00:rgba(255,255,255,0);
  --black-90:rgba(0,0,0,0.9);
  --black-80:rgba(0,0,0,0.8);
  --black-70:rgba(0,0,0,0.7);
  --black-60:rgba(0,0,0,0.6);
  --black-50:rgba(0,0,0,0.5);
  --black-40:rgba(0,0,0,0.4);
  --black-30:rgba(0,0,0,0.3);
  --black-20:rgba(0,0,0,0.2);
  --black-10:rgba(0,0,0,0.1);
  --black-04:rgba(0,0,0,0.04);
  --black-00:rgba(0,0,0,0);

  --color-font:#020202;
  --color-background:#f2f2f2;
  --color-background-alt:#111111;
  --color-primary-focus:#e0e0e0;
  --color-filter-background:rgb(42,42,42);
  --color-nav:#ffffff;

  /* ---- 2. Derived ramps ---- */
  --gray-0:var(--white);
  --gray-1000:var(--black);
  --gray-025:#fcfcfb;
  --gray-150:#e7e7e3;

  --green-50:color-mix(in oklab,var(--green) 10%,var(--white));
  --green-100:color-mix(in oklab,var(--green) 18%,var(--white));
  --green-200:color-mix(in oklab,var(--green) 34%,var(--white));
  --green-300:color-mix(in oklab,var(--green) 55%,var(--white));
  --green-400:color-mix(in oklab,var(--green) 78%,var(--white));
  --green-500:var(--green);
  --green-600:color-mix(in oklab,var(--green) 88%,var(--black));
  --green-700:color-mix(in oklab,var(--green) 72%,var(--black));
  --green-800:color-mix(in oklab,var(--green) 55%,var(--black));
  --green-900:color-mix(in oklab,var(--green) 38%,var(--black));

  --blue-100:color-mix(in oklab,var(--blue) 14%,var(--white));
  --blue-500:var(--blue);
  --blue-600:color-mix(in oklab,var(--blue) 74%,var(--black));

  --red-100:color-mix(in oklab,var(--red) 14%,var(--white));
  --red-500:var(--red);
  --red-600:color-mix(in oklab,var(--red) 78%,var(--black));

  --yellow-100:color-mix(in oklab,var(--yellow) 30%,var(--white));
  --yellow-500:var(--yellow);

  --orange-100:color-mix(in oklab,var(--orange) 16%,var(--white));
  --orange-500:var(--orange);
  --orange-600:color-mix(in oklab,var(--orange) 68%,var(--black));
  /* legacy alias — warning states used to be amber */
  --amber-100:var(--orange-100);
  --amber-500:var(--orange-500);
  --amber-600:var(--orange-600);

  /* ---- Extended hues ----
     --violet is a first-class brand hue (it replaces the source CSS's --purple, which
     was an off-white and almost certainly a mistake). --teal and --lime are MIXED FROM
     the brand hues, never sampled, so they sit at the same chroma level. */
  --violet-100:color-mix(in oklab,var(--violet) 14%,var(--white));
  --violet-500:var(--violet);
  --violet-600:color-mix(in oklab,var(--violet) 76%,var(--black));
  --teal:color-mix(in oklab,var(--green) 62%,var(--blue) 38%);
  --lime:color-mix(in oklab,var(--yellow) 52%,var(--green) 48%);
  /* Five more hues, minted the same way and for the same reason teal and lime
     were: the suite outgrew eight accent slots. Twelve applications were sharing
     them by September 2026, four of them doubled up and one slot claimed three
     times, which is not a naming problem — it is a palette that ran out. Each
     of these sits between two adjacent brand hues at the same chroma level, so
     nothing here is a new colour, only a new position on a wheel the brand
     already defines. */
  --amber:color-mix(in oklab,var(--orange) 55%,var(--yellow) 45%);
  --coral:color-mix(in oklab,var(--red) 58%,var(--orange) 42%);
  --rose:color-mix(in oklab,var(--red) 55%,var(--violet) 45%);
  --indigo:color-mix(in oklab,var(--violet) 60%,var(--blue) 40%);
  --cyan:color-mix(in oklab,var(--blue) 62%,var(--teal) 38%);
  --plum:color-mix(in oklab,var(--violet) 66%,var(--red) 34%);
  /* Slot 15, minted 6 September 2026 for opentagged. By then every adjacent
     pair of brand hues already had a midpoint, so this one is a midpoint of two
     minted slots — blue and indigo, the widest gap left on the wheel at 44.7°.
     Measured: 6.5 ΔE from blue and 6.3 from indigo (OKLab ×100), which is the
     spacing the ring already has elsewhere (rose and plum sit 6.9 apart). That
     is fine for product accents, which are never seen side by side, and it does
     mean the ring is now at its practical limit: a sixteenth hue at this chroma
     would land under 5 ΔE from both neighbours. Separate by lightness or chroma
     instead, or let two products share a hue deliberately. */
  --azure:color-mix(in oklab,var(--blue) 50%,var(--indigo) 50%);
  /* Slot 16. The hue ring is full; this one separates by lightness and
     chroma instead, per ACCENT-SLOTS.md. Ledger ink: a deep blue that cannot
     be mistaken for a red or green result state. */
  --ink:color-mix(in oklab,var(--blue) 54%,var(--black) 46%);
  /* Slot 17, minted the same way: a hue deepened, not the ring bisected. */
  --mulberry:color-mix(in oklab,var(--violet) 58%,var(--black) 42%);
  --petrol:color-mix(in oklab,var(--cyan) 62%,var(--black) 38%);
  /* Slot 19. The first deepening on the warm side — ink, mulberry and petrol
     are all cool, and a fourth cool one would have crowded them. Deep enough
     to carry white type, because this one is used as a key fill. */
  --rust:color-mix(in oklab,var(--orange) 56%,var(--black) 44%);
  /* Slot 20. Yellow deepened — the only brand hue still undeepened that is not
     a result state. Green and red were unavailable to opendocscan for the
     reason recorded three times in ACCENT-SLOTS.md: a scanner reports "read"
     in green and "failed" in red, so an accent near either says the wrong
     thing about the row it tints. 31.1 dE from its nearest neighbour (rust),
     which is the widest separation any deepened slot has. */
  --brass:color-mix(in oklab,var(--yellow) 56%,var(--black) 44%);
  /* Slot 21. Not a deepening and not a bisection of the ring — by September
     2026 both were exhausted: every candidate deepened from the green/teal
     family landed under 5 dE from petrol, which is the crowding limit stated
     below. This one was found by searching the ring's own chroma band
     (0.06–0.15 C) at usable accent lightness for the largest gap, then
     expressed as a mix rather than kept as the sampled hex. 12.3 dE from its
     nearest neighbour (rust) and 14.1 from the mulberry it is built on.
     opennotetaker paints success green, failure red and warnings orange, so
     all three of those families were excluded before separation was
     considered at all. Carries white type at 6.2:1; as *text* on a dark page
     it is only 3.4:1, so small type in the accent lifts toward white the way
     brass does. */
  --wine:color-mix(in oklab,var(--mulberry) 62%,var(--red) 38%);
  /* Slot 22, minted 8 September 2026 for opentabs — the first *lift* in the
     ring, where 16-21 are all deepenings. Deepening was unavailable: opentabs
     paints success green, failure red and warnings orange, and every deepening
     of what remained landed in the lane ink, petrol and mulberry already hold.
     Lifting petrol instead moves along lightness in the other direction and
     opens ground nothing occupies: 14.3 dE from petrol itself, 14.5 from brass
     and azure, and 18.4 from the nearest of the product's own result colours.
     Chosen over the ring's widest gap (an olive at H 106, 16.3 dE) because
     opentabs' mark has been a blue-cyan since it was drawn, and the register
     asks for separation, not for a product to stop looking like itself.
     It is a fill before it is anything else — the mark is a rounded square
     with white bars on it — and it carries those bars at 3.90:1, where the
     slot-2 blue it replaces managed 2.29:1. The icon got more legible at 16px
     by being moved off a colour it was never entitled to. */
  --slate:color-mix(in oklab,var(--petrol) 74%,var(--white));
  /* Slot 23, minted 11 September 2026 for opensync — the sync engine's own
     relay service. This is the olive the slot-22 note measured and set aside:
     the ring's widest remaining gap, 15.1 dE from its nearest neighbours
     (green and orange) where the crowding threshold is 5. It was set aside for
     opentabs because that product's mark was already blue-cyan; opensync has
     no drawn mark, and what it *was* using — a private #0C6E77 in its client
     stylesheet, never tokenised — sits 3.8 dE from petrol, inside the
     threshold and squarely in openfilesend's lane. It was not entitled to it.
     The usual elimination does not bind here: opensync's surfaces paint no
     success or failure colour at all, only an accent, so the warm families
     that were unavailable to opendocscan and opentabs are available to this
     one. 7.01:1 as accent text on the dark page; 2.81:1 on white, so on a
     light ground it deepens toward brass rather than being used raw. As a fill
     it takes black glyphs at 7.48:1, not white at 2.81:1. */
  --olive:color-mix(in oklab,var(--brass) 57%,var(--yellow) 43%);
  /* Slot 24, iris: minted 14 Sep 2026 for openphotoedit. The ring had no
     room at full chroma; violet deepened by ink lands 13.4 dE from its nearest
     slot (violet) and 20.1 from every result colour. See ACCENT-SLOTS.md. */
  --iris:color-mix(in oklab,var(--violet) 56%,var(--ink));

  /* ---- Accent slots ----
     Generic, product-neutral names. Any application built on this system claims a slot
     rather than a colour, so palettes can be re-pointed centrally without touching code.
     Rule: one slot per application, never two in a single surface.
     Who holds which is recorded in tokens/ACCENT-SLOTS.md — check it before
     claiming one. No single product can see the collision it is about to make. */
  --accent-1:var(--green);
  --accent-2:var(--blue);
  --accent-3:var(--violet);
  --accent-4:var(--orange);
  --accent-5:var(--red);
  --accent-6:var(--yellow);
  --accent-7:var(--teal);
  --accent-8:var(--lime);
  --accent-9:var(--amber);
  --accent-10:var(--coral);
  --accent-11:var(--rose);
  --accent-12:var(--indigo);
  --accent-13:var(--cyan);
  --accent-14:var(--plum);
  --accent-15:var(--azure);
  --accent-16:var(--ink);
  --accent-17:var(--mulberry);
  --accent-18:var(--petrol);
  --accent-19:var(--rust);
  --accent-20:var(--brass);
  --accent-21:var(--wine);
  --accent-22:var(--slate);
  --accent-23:var(--olive);
  --accent-24:var(--iris);

  /* ---- App accents ----
     The OpenApps suite's own assignment. These are aliases: consuming products should
     either re-point them or use the --accent-N slots directly. */
  --app-notes:var(--accent-6);
  --app-tasks:var(--accent-1);
  --app-calendar:var(--accent-5);
  --app-mail:var(--accent-4);
  --app-files:var(--accent-7);
  --app-draw:var(--accent-3);
  --app-terminal:var(--accent-8);
  --app-vault:var(--gray-600);
  /* OpenScreenCapture — a product in the family, with its own mobile app and extension. */
  --app-screenshot:var(--accent-2);
  /* Shipped products. These were defined only in downstream copies of this
     file until 7 September 2026, which is why --app-pdfedit resolved to
     nothing wherever the local copy was not the one in use. Promoted here so
     the source of truth actually holds them. */
  --app-pdfedit:var(--accent-5);
  --app-frame:var(--accent-3);
  /* OpenSubs was OpenVidSub. The product renamed; the token had not, and
     opensubs' local copy carried a note asking for exactly this rename.
     --app-vidsub stays as a legacy alias so no existing surface breaks. */
  --app-opensubs:var(--accent-4);
  --app-vidsub:var(--app-opensubs);
  /* OpenDocScan. Slot 20; see the note on --brass. */
  --app-docscan:var(--accent-20);
  /* opentabs held slot 2 verbatim until 8 September 2026 — blue, which
     openinbox claims and the shipped opencapture also uses. See ACCENT-SLOTS.md. */
  --app-opentabs:var(--accent-22);

  /* ---- 3. Semantic aliases (use these) ---- */
  --brand:var(--green);
  --brand-strong:var(--green-600);
  --brand-soft:var(--green-50);
  --brand-contrast:var(--black);

  --bg-page:var(--color-background);
  --bg-subtle:var(--gray-050);
  --bg-sunken:var(--gray-100);
  --surface-card:var(--white);
  --surface-raised:var(--white);
  --surface-inverse:var(--color-background-alt);
  --surface-hover:var(--black-04);
  --surface-active:var(--gray-100);
  --surface-selected:var(--green-50);

  --text-strong:var(--color-font);
  --text-body:var(--gray-800);
  --text-muted:var(--gray-600);
  --text-faint:color-mix(in oklab, var(--gray-500) 30%, var(--gray-600));
  --text-inverse:var(--white);
  --text-brand:var(--green-700);
  --text-link:var(--color-font);
  --text-link-hover:var(--green-700);

  --border-hairline:var(--gray-200);
  --border-strong:var(--gray-300);
  --border-inverse:var(--white-10);
  --border-focus:var(--color-font);

  --success-fg:var(--green-700);
  --success-bg:var(--green-50);
  --warning-fg:var(--orange-600);
  --warning-bg:var(--orange-100);
  --danger-fg:var(--red-600);
  --danger-bg:var(--red-100);
  --info-fg:var(--blue-600);
  --info-bg:var(--blue-100);

  --focus-ring:0 0 0 2px var(--bg-page),0 0 0 4px var(--color-font);
}

/* ---- Brand mark ----
   The mark is typographic: the wordmark sets in the display font, the monogram is a
   numeral in a squircle. These tokens let a host re-skin it without editing the SVGs.
   The BrandMark component reads them, so re-pointing these re-skins every surface.
   Dark overrides live in the shared dark block below, never here. */
:root{
  --logo-fg:var(--color-font);
  --logo-dot:var(--brand);
  --logo-tile-bg:var(--color-font);
  --logo-tile-fg:var(--brand);
  --logo-tile-radius:0.22em;
  --logo-tracking:-0.04em;
}

/* ---- Dark scope ----
   Declared ONCE and emitted into both dark selectors below. If you add a dark override,
   add it to both blocks or neither — they are required to be character-identical.
   .oa-dark  = opt in on any container.
   .oa-auto  = on <html>, follows the OS/browser setting. */
.oa-dark{
  --bg-page:var(--color-background-alt);
  --bg-subtle:var(--gray-950);
  --bg-sunken:var(--black);
  --surface-card:var(--gray-950);
  --surface-raised:var(--gray-900);
  --surface-inverse:var(--white);
  --surface-hover:var(--white-04);
  --surface-active:var(--white-10);
  --surface-selected:color-mix(in oklab,var(--green) 20%,transparent);
  --text-strong:var(--white);
  --text-body:var(--white-70);
  --text-muted:var(--white-60);
  --text-faint:var(--white-50);
  --text-inverse:var(--black);
  --text-brand:var(--green);
  --text-link:var(--white);
  --text-link-hover:var(--green);
  --border-hairline:var(--white-10);
  --border-strong:var(--white-20);
  --border-focus:var(--green);
  --brand-soft:color-mix(in oklab,var(--green) 20%,transparent);
  --brand-contrast:var(--black);
  --success-bg:color-mix(in oklab,var(--green) 18%,transparent);
  --success-fg:var(--green);
  --danger-bg:color-mix(in oklab,var(--red) 20%,transparent);
  --danger-fg:var(--red);
  --warning-bg:color-mix(in oklab,var(--orange) 20%,transparent);
  --warning-fg:var(--orange);
  --info-bg:color-mix(in oklab,var(--blue) 20%,transparent);
  --info-fg:var(--blue);
  --focus-ring:0 0 0 2px var(--bg-page),0 0 0 4px var(--green);
  --logo-fg:var(--white);
  --logo-tile-bg:var(--white);
  --logo-tile-fg:var(--color-font);
}
@media (prefers-color-scheme:dark){
  .oa-auto{
    --bg-page:var(--color-background-alt);
    --bg-subtle:var(--gray-950);
    --bg-sunken:var(--black);
    --surface-card:var(--gray-950);
    --surface-raised:var(--gray-900);
    --surface-inverse:var(--white);
    --surface-hover:var(--white-04);
    --surface-active:var(--white-10);
    --surface-selected:color-mix(in oklab,var(--green) 20%,transparent);
    --text-strong:var(--white);
    --text-body:var(--white-70);
    --text-muted:var(--white-60);
    --text-faint:var(--white-50);
    --text-inverse:var(--black);
    --text-brand:var(--green);
    --text-link:var(--white);
    --text-link-hover:var(--green);
    --border-hairline:var(--white-10);
    --border-strong:var(--white-20);
    --border-focus:var(--green);
    --brand-soft:color-mix(in oklab,var(--green) 20%,transparent);
    --brand-contrast:var(--black);
    --success-bg:color-mix(in oklab,var(--green) 18%,transparent);
    --success-fg:var(--green);
    --danger-bg:color-mix(in oklab,var(--red) 20%,transparent);
    --danger-fg:var(--red);
    --warning-bg:color-mix(in oklab,var(--orange) 20%,transparent);
    --warning-fg:var(--orange);
    --info-bg:color-mix(in oklab,var(--blue) 20%,transparent);
    --info-fg:var(--blue);
    --focus-ring:0 0 0 2px var(--bg-page),0 0 0 4px var(--green);
    --logo-fg:var(--white);
    --logo-tile-bg:var(--white);
    --logo-tile-fg:var(--color-font);
  }
}

:root{
  --font-sans:"Geist","Helvetica Neue",Arial,sans-serif;
  --font-display:"Geist","Helvetica Neue",Arial,sans-serif;
  --font-mono:"Geist Mono",ui-monospace,SFMono-Regular,Menlo,monospace;

  --weight-light:300;
  --weight-regular:400;
  --weight-medium:500;
  --weight-bold:700;

  /* Sizes — 15px body. Product UI lives between 12 and 20. */
  --text-2xs:11px;
  --text-xs:12px;
  --text-sm:13px;
  --text-base:15px;
  --text-md:17px;
  --text-lg:20px;
  --text-xl:24px;
  --text-2xl:32px;
  --text-3xl:40px;
  --text-4xl:56px;
  --text-5xl:72px;
  --text-6xl:96px;

  --leading-tight:1.05;
  --leading-snug:1.2;
  --leading-normal:1.45;
  --leading-relaxed:1.6;

  /* Optical tracking: the bigger the type, the tighter it sets */
  --tracking-display:-0.035em;
  --tracking-heading:-0.02em;
  --tracking-body:-0.005em;
  --tracking-wide:0.02em;
  --tracking-caps:0.08em;

  /* Composed roles */
  --type-display:var(--weight-medium) var(--text-4xl)/var(--leading-tight) var(--font-display);
  --type-h1:var(--weight-medium) var(--text-3xl)/1.1 var(--font-display);
  --type-h2:var(--weight-medium) var(--text-2xl)/1.15 var(--font-display);
  --type-h3:var(--weight-medium) var(--text-xl)/1.25 var(--font-sans);
  --type-h4:var(--weight-medium) var(--text-lg)/1.3 var(--font-sans);
  --type-body-lg:var(--weight-regular) var(--text-md)/var(--leading-relaxed) var(--font-sans);
  --type-body:var(--weight-regular) var(--text-base)/var(--leading-normal) var(--font-sans);
  --type-ui:var(--weight-medium) var(--text-sm)/1.3 var(--font-sans);
  --type-caption:var(--weight-regular) var(--text-xs)/1.35 var(--font-sans);
  --type-mono:var(--weight-regular) var(--text-sm)/1.5 var(--font-mono);
  --type-eyebrow:var(--weight-medium) var(--text-xs)/1.2 var(--font-sans);
}

/* 4px base grid. Product density is tight: most UI gaps are 8–16. */
:root{
  --space-0:0px;
  --space-1:4px;
  --space-2:8px;
  --space-3:12px;
  --space-4:16px;
  --space-5:20px;
  --space-6:24px;
  --space-7:28px;
  --space-8:32px;
  --space-10:40px;
  --space-12:48px;
  --space-14:56px;
  --space-16:64px;
  --space-20:80px;
  --space-24:96px;
  --space-32:128px;

  /* Layout */
  --container-max:1200px;
  --container-prose:680px;
  --gutter-page:24px;
  --gutter-page-lg:48px;
  --section-y:96px;
  --control-h-sm:28px;
  --control-h-md:34px;
  --control-h-lg:42px;
  --sidebar-w:248px;
  --rail-w:56px;
  --topbar-h:52px;
  --header-height:64px;
  --footer-height:64px;
  /* Browser-extension geometry. Chrome caps popups at 800×600. */
  --popup-w:380px;
  --popup-h:560px;
  --options-max:720px;
}

/* Platform foundations — one system, five surfaces:
   local app, web app, mobile app, browser extension, embedded account SDK.
   Everything here is geometry. Colour, type and motion never change per platform. */
:root{
  /* ---- Touch ----
     44px is the floor for anything tappable. Never ship a smaller hit target. */
  --touch-min:44px;
  --control-h-touch-sm:40px;
  --control-h-touch-md:48px;
  --control-h-touch-lg:56px;

  /* ---- Mobile layout ---- */
  --mobile-gutter:16px;
  --navbar-h:52px;
  --tabbar-h:56px;
  --safe-top:env(safe-area-inset-top,0px);
  --safe-bottom:env(safe-area-inset-bottom,0px);
  --sheet-radius:var(--radius-2xl);
  --list-row-h:52px;

  /* ---- Local (desktop) app window ---- */
  --titlebar-h:38px;
  --window-min-w:880px;
  --window-min-h:560px;
  --window-radius:10px;

  /* ---- Embedded SDK ----
     The account/credits surfaces render inside a host app, so they size to a card,
     not a page. --sdk-max is the widest an embedded panel ever gets. */
  --sdk-max:420px;
  --sdk-wide:560px;

  /* ---- Breakpoints ----
     Declared for reference; media queries must use the literal px values. */
  --bp-sm:600px;
  --bp-md:900px;
  --bp-lg:1200px;
  --bp-xl:1440px;
}

/* Touch devices get bigger controls and one step more text, automatically.
   Every component reads --control-h-*, so nothing needs a mobile variant. */
@media (pointer:coarse){
  :root{
    --control-h-sm:var(--control-h-touch-sm);
    --control-h-md:var(--control-h-touch-md);
    --control-h-lg:var(--control-h-touch-lg);
    --text-xs:13px;
    --text-sm:14px;
    --list-row-h:56px;
  }
}

:root{
  --radius-xs:4px;
  --radius-sm:6px;
  --radius-md:8px;
  --radius-lg:12px;
  --radius-xl:16px;
  --radius-2xl:24px;
  --radius-full:999px;
  --border-width:1px;
  --border-width-strong:1.5px;
}

/* Shadows are quiet. Hierarchy comes from hairlines first, elevation second.
   All shadows are pure black at low alpha, from the brand's black-XX ramp. */
:root{
  --shadow-none:none;
  --shadow-xs:0 1px 1px var(--black-04);
  --shadow-sm:0 1px 2px rgba(0,0,0,0.06),0 1px 1px var(--black-04);
  --shadow-md:0 2px 4px rgba(0,0,0,0.06),0 4px 12px rgba(0,0,0,0.06);
  --shadow-lg:0 4px 8px rgba(0,0,0,0.05),0 12px 32px rgba(0,0,0,0.09);
  --shadow-xl:0 8px 16px rgba(0,0,0,0.06),0 24px 64px rgba(0,0,0,0.12);
  --shadow-inset-top:inset 0 1px 0 var(--white-10);
  --shadow-key:0 1px 0 var(--black-10);
  --blur-panel:saturate(180%) blur(20px); /* @kind other */
  --scrim:var(--black-50);
}

/* Motion is short and mechanical. Nothing bounces, nothing overshoots. */
:root{
  --duration-instant:80ms; /* @kind other */
  --duration-fast:120ms; /* @kind other */
  --duration-base:180ms; /* @kind other */
  --duration-slow:260ms; /* @kind other */
  --duration-page:400ms; /* @kind other */
  --ease-standard:cubic-bezier(0.2,0,0,1); /* @kind other */
  --ease-out:cubic-bezier(0.16,1,0.3,1); /* @kind other */
  --ease-in:cubic-bezier(0.4,0,1,1); /* @kind other */
  --ease-linear:linear; /* @kind other */
  --transition-control:background-color var(--duration-fast) var(--ease-standard),border-color var(--duration-fast) var(--ease-standard),color var(--duration-fast) var(--ease-standard),box-shadow var(--duration-fast) var(--ease-standard),opacity var(--duration-fast) var(--ease-standard);
}
@media (prefers-reduced-motion:reduce){
  :root{--duration-instant:0ms; /* @kind other */ --duration-fast:0ms; /* @kind other */ --duration-base:0ms; /* @kind other */ --duration-slow:0ms; /* @kind other */ --duration-page:0ms /* @kind other */}
}

