/* Lantern — a design language for the web.
 *
 * The CSS sibling of github.com/lapfelix/Lantern (UIKit). Same model, same
 * tokens, same banned list. No dependencies, no build step, no @import.
 *
 * THE MODEL
 * Everything is one sheet of material. A surface is in one of three physical
 * states: raised (a card), sunken (a well you put content into), lit (an accent
 * surface that emits). Depth comes from tone and edge, not from blur: a few
 * percent of tonal gradient, a 1px specular lip on the top edge, a hairline
 * border, a tight neutral contact shadow, and a pixel-fine grain.
 *
 * WHAT IS BANNED, AND WHY — this list is the load-bearing part.
 *   - No white gloss sweeping half a control's height. A specular lip is 1px.
 *   - No shadow tinted with the control's own colour. Contact shadows are neutral.
 *   - No glow behind anything that isn't genuinely the light source on its screen.
 *   - No saturated fills. Status hues are muted on purpose — four saturated grade
 *     keys side by side read as a toy.
 * If you find yourself widening a blur or brightening a gloss to make something
 * "pop", the fix is almost always tone or spacing instead.
 *
 * TWO TRAPS, both of which shipped once on iOS
 *   - Fade white into transparent WHITE, never `transparent`/black. Interpolating
 *     white→rgb(0 0 0/0) passes through a grey veil across the upper half of
 *     every card. Every gradient here spells out `rgb(255 255 255 / 0)`.
 *   - Build a pattern tile at the device pixel ratio. A tile sized in CSS px
 *     magnifies on a 2x/3x screen and reads as static, not grain — hence the
 *     `--ln-grain-size` overrides under `min-resolution` below.
 *
 * THEMING
 * Tokens resolve through `light-dark()`, so switching a subtree is one property:
 *   <html data-theme="dark">  ·  data-theme="light"  ·  omit for the OS setting.
 * A named palette is a second, independent attribute that composes with both
 * modes and with the flat style:
 *   <html data-ln-theme="instrument">  (see the Instrument theme section)
 *
 * YOUR OWN ACCENT
 * Everything here is neutral except the accent. Set one hue and the wash, the
 * ember and the fill gradients follow:
 *   :root { --ln-accent-light: #1478CE; --ln-accent-dark: #57ADEA; }
 * `--ln-on-accent` is the one thing worth overriding by hand — the ink over a
 * filled control has to be decided per interface style, and the default pair
 * (white in light, near-black in dark) assumes an accent that darkens for light
 * mode the way Lantern's own azure does.
 */

/* ========================================================================== *
 * Tokens
 * ========================================================================== */

:root {
  color-scheme: light dark;

  /* -- Accent ------------------------------------------------------------- */
  /* The two literals an app substitutes. Everything accent-derived below
     reads `--ln-accent`, so overriding these two is enough. */
  --ln-accent-light: #1478ce;
  --ln-accent-dark: #57adea;
  --ln-accent: light-dark(var(--ln-accent-light), var(--ln-accent-dark));
  /* Ink on a filled accent surface. */
  --ln-on-accent: light-dark(#ffffff, #07131c);
  /* A tinted wash for selected rows and quiet accent chips. Heavier in dark:
     a 10% tint that reads as a wash on paper disappears against a dark page. */
  --ln-accent-wash: light-dark(
    color-mix(in srgb, var(--ln-accent) 10%, transparent),
    color-mix(in srgb, var(--ln-accent) 16%, transparent)
  );
  /* The warm counterweight — progress, streaks, mastery. */
  --ln-ember: light-dark(#a5701f, #d8a05c);
  --ln-on-ember: light-dark(#ffffff, #1c1206);

  /* -- Page --------------------------------------------------------------- */
  /* Both modes are a vertical wash rather than a flat fill, so a card floating
     on the page has something to be lit against. */
  --ln-canvas-top: light-dark(#f5f4f1, #18181b);
  --ln-canvas-bottom: light-dark(#eae9e5, #0c0c0e);
  /* Flat stand-in, for anything that can't host a gradient. */
  --ln-canvas: light-dark(#f0efeb, #121214);

  /* -- Surfaces ----------------------------------------------------------- */
  /* A hair off white, so the lip on the top edge has something to be brighter than. */
  --ln-surface: light-dark(#fcfcfb, #1d1d21);
  /* A second surface nested inside the first (a chip inside a card). */
  --ln-surface-quiet: light-dark(#e9e7e1, #26262b);
  /* A recessed well. Barely off the page tone — a field you type into should
     read as a dip in the surface, not a dark trough cut out of it. */
  --ln-well: light-dark(#efeeea, #17171b);

  /* -- Ink ---------------------------------------------------------------- */
  --ln-ink: light-dark(#17171a, #f3f3f1);
  /* Secondary meets 4.5:1 on the canvas, a surface, a quiet surface and a well
     in both modes (5.6:1 at worst in light; it was 4.1:1 at 0.58). Tertiary
     meets 3:1, for placeholders, glyphs and disabled ink, never for body text.
     `--ln-ink-quiet` is the small-text tier (captions, micro, labels, hints):
     the same value today, named so an app that lightens secondary for large
     type does not drag its captions under AA. */
  --ln-ink-secondary: light-dark(rgb(23 23 26 / 0.68), rgb(243 243 241 / 0.6));
  --ln-ink-tertiary: light-dark(rgb(23 23 26 / 0.5), rgb(243 243 241 / 0.42));
  --ln-ink-quiet: light-dark(rgb(23 23 26 / 0.68), rgb(243 243 241 / 0.6));
  /* Placeholder text is still text, so it needs 4.5:1, which tertiary does not
     reach in the stock palette. It stays a step lighter than secondary so a
     hint never reads as a typed value. */
  --ln-ink-placeholder: light-dark(rgb(23 23 26 / 0.62), rgb(243 243 241 / 0.52));
  /* Long-form body text: a step under the ink so a page of it reads calm. */
  --ln-ink-prose: light-dark(rgb(23 23 26 / 0.84), rgb(243 243 241 / 0.78));

  /* -- Status. Muted on purpose. ------------------------------------------ */
  /* These are tuned as INK — a status word, a glyph, a hairline. */
  --ln-positive: light-dark(#2e7a5a, #63be95);
  --ln-caution: light-dark(#99721e, #d1a65b);
  --ln-critical: light-dark(#af4a42, #dd7c72);
  /* And these as FILLS, which is a different job: the dark-mode hues above are
     lightened so they read as ink on a dark page, and at that lightness they
     cannot carry white. So a lit status surface starts from the light-mode hue
     in both modes, deepened toward the media recess rather than desaturated, and
     each gets its own ink. Reaching for `--ln-positive` as a background is the
     mistake this pair exists to prevent.

     Positive and critical carry white unchanged (5.2:1 and 5.4:1). Caution does
     not — `--ln-caution` is the lightest of the three and white on it measures
     4.4:1 — so its fill is darkened until it does (5.3:1). The rule is "the
     status hue, dark enough for its own ink", and only caution needs the second
     half of that. */
  --ln-positive-fill: light-dark(#2e7a5a, #2a6b50);
  --ln-caution-fill: light-dark(#8a6519, #7d5c18);
  --ln-critical-fill: light-dark(#af4a42, #963f38);
  --ln-on-positive: #ffffff;
  --ln-on-caution: #ffffff;
  --ln-on-critical: #ffffff;

  /* Grading a flash card, worst → best. Easy lands on the brand accent so the
     happy path is the app's own colour. */
  --ln-grade-again: var(--ln-critical);
  --ln-grade-hard: var(--ln-caution);
  --ln-grade-good: var(--ln-positive);
  --ln-grade-easy: var(--ln-accent);

  /* -- Interaction washes ------------------------------------------------ */
  /* Derived from the accent, so a brand hue carries into them. Hover is the
     lightest; the "now playing" word is a step heavier; a search hit is the
     one warm highlight, because a match is not a selection. */
  --ln-hover-wash: light-dark(
    color-mix(in srgb, var(--ln-accent) 7%, transparent),
    color-mix(in srgb, var(--ln-accent) 12%, transparent)
  );
  --ln-current-wash: light-dark(
    color-mix(in srgb, var(--ln-accent) 16%, transparent),
    color-mix(in srgb, var(--ln-accent) 26%, transparent)
  );
  --ln-highlight: light-dark(#fde9a8, #5a4a12);
  --ln-answer-wash: var(--ln-accent-wash);
  /* Recording. Warmer and brighter than critical: it means "on air", not
     "wrong". */
  --ln-live: light-dark(#c9372c, #ff6b5e);

  /* -- Edges -------------------------------------------------------------- */
  --ln-hairline: light-dark(rgb(23 23 26 / 0.09), rgb(255 255 255 / 0.07));
  --ln-hairline-faint: light-dark(rgb(23 23 26 / 0.055), rgb(255 255 255 / 0.045));
  /* Opaque, for the cases where a hairline is a *fill* rather than an edge — a
     divider drawn as a block, a keyline over an unknown backdrop. The
     translucent tokens above vanish there. */
  --ln-hairline-strong: color-mix(in srgb, var(--ln-ink) 14%, var(--ln-surface));
  /* The edge of a control that has no text of its own (a field, a switch
     track, a slider). A theme raises it to 3:1 without darkening every card. */
  --ln-control-edge: var(--ln-hairline);
  --ln-field-border: var(--ln-hairline-faint);
  /* The focused field's edge is its focus indicator, so it takes the ring's
     full colour: at 55% of the accent it measured 2:1 against the well. */
  --ln-field-focus: var(--ln-focus);
  /* The keyboard focus ring. */
  --ln-focus: var(--ln-accent);
  /* Selected text. Heavier than the accent wash, which is a hover tint and too
     faint to show a selection at a glance. */
  --ln-selection: light-dark(
    color-mix(in srgb, var(--ln-accent) 24%, transparent),
    color-mix(in srgb, var(--ln-accent) 36%, transparent)
  );

  /* -- Charts ------------------------------------------------------------- */
  /* No component draws a chart; these give a product's charts a fixed series
     order that follows the palette. Assign in order, never cycle. */
  --ln-series-1: var(--ln-accent);
  --ln-series-2: var(--ln-ember);
  --ln-series-3: var(--ln-positive);
  --ln-series-4: var(--ln-caution);
  --ln-series-5: var(--ln-critical);
  --ln-series-6: var(--ln-ink-secondary);
  --ln-chart-grid: var(--ln-hairline);
  --ln-chart-axis: var(--ln-ink-tertiary);

  /* -- Over media --------------------------------------------------------- */
  /* Video and artwork are their own ground: the neutral ink tokens flip with
     the interface style, so over a frame that does not they go unreadable in
     one mode. These do not flip. */
  --ln-media: #0e0e10;
  --ln-on-media: #ffffff;
  --ln-on-media-secondary: rgb(255 255 255 / 0.72);
  /* A well over artwork is invisible — the recess reads as part of the frame —
     so a track laid on media is a wash of the over-media ink instead. */
  --ln-on-media-track: rgb(255 255 255 / 0.22);
  /* A fill laid on media. A theme whose accent darkens for light mode lifts it here. */
  --ln-on-media-accent: var(--ln-accent);
  --ln-media-chip: rgb(0 0 0 / 0.55);
  /* The veil under a modal. Lighter in light mode: a near-black scrim over a
     paper page reads as the lights going out rather than as a layer above it. */
  --ln-scrim: light-dark(rgb(23 23 26 / 0.28), rgb(0 0 0 / 0.6));
  /* A translucent floating material — a bar or a panel over content it has to
     stay legible against. Paired with a backdrop-filter at the use site; on its
     own it is just a tinted wash of the page. */
  --ln-glass: color-mix(in srgb, var(--ln-canvas) 82%, transparent);

  /* -- Spacing. A 4px grid. ---------------------------------------------- */
  --ln-hair: 2px; /* between two lines of the same thought (a word and its gloss) */
  --ln-xs: 4px;
  --ln-sm: 8px; /* the default gap between siblings */
  --ln-md: 12px;
  --ln-lg: 16px; /* page margins, card padding */
  --ln-xl: 24px; /* between sections */
  --ln-xxl: 32px;

  /* -- Radius. Nothing is ever sharp. ------------------------------------ */
  --ln-r-xs: 8px; /* chips, small controls */
  --ln-r-sm: 12px; /* artwork, nested surfaces */
  --ln-r-md: 16px; /* the standard card */
  --ln-r-lg: 22px; /* a large panel, a now-playing bar */
  --ln-r-xl: 28px; /* a hero card */
  --ln-r-pill: 999px;

  /* -- Depth ------------------------------------------------------------ */
  /* Scales the material: shadows, sheen, lips, inner shadows and button gloss.
     1 is the full finish, `data-ln-style="soft"` sets 0.55 and drops the grain,
     and flat removes the material outright. */
  --ln-depth: 1;

  /* A fine monochrome dither, tiled. Real materials are not perfectly smooth,
     and a couple of percent of grain is most of the difference between a
     surface and a coloured rectangle. */
  --ln-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='96' height='96'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='96' height='96' filter='url(%23n)' opacity='0.05'/%3E%3C/svg%3E");
  --ln-grain-size: 96px 96px;

  /* -- Motion ------------------------------------------------------------- */
  --ln-t-tap: 0.18s; /* a press-down / release. Short enough to feel mechanical. */
  --ln-t-move: 0.32s; /* something appearing or moving on screen */
  --ln-ease: cubic-bezier(0.32, 0.72, 0.24, 1);
  --ln-ease-spring: cubic-bezier(0.2, 0.9, 0.24, 1.02);

  /* -- Type --------------------------------------------------------------- */
  /* Sizes are rem, so they scale with the reader's root font size — the web's
     Dynamic Type. Never freeze a px size for body text. */
  --ln-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --ln-font-serif: ui-serif, Georgia, 'Times New Roman', serif;
  --ln-font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* Arabic is the subject, not a translation of it — its own stack and, below,
     its own scale and leading. */
  --ln-font-ar:
    -apple-system, 'SF Arabic', 'Geeza Pro', 'Noto Naskh Arabic', 'Segoe UI', Tahoma, serif;

  --ln-fs-display: clamp(1.75rem, 1.35rem + 2vw, 2.125rem); /* 34 */
  --ln-fs-title: 1.375rem; /* 22 */
  --ln-fs-headline: 1.0625rem; /* 17 semibold */
  --ln-fs-body: 1.0625rem; /* 17 */
  --ln-fs-callout: 0.9375rem; /* 15 */
  --ln-fs-caption: 0.8125rem; /* 13 */
  --ln-fs-micro: 0.6875rem; /* 11 semibold — badges, timestamps, tags */

  --ln-fs-ar-hero: clamp(2rem, 1.5rem + 2.4vw, 2.375rem); /* 38 */
  --ln-fs-ar-title: 1.875rem; /* 30 */
  --ln-fs-ar-row: 1.375rem; /* 22 */
  --ln-fs-ar-body: 1.1875rem; /* 19 */
  --ln-fs-ar-caption: 1rem; /* 16 */
  --ln-lh-ar: 1.22; /* Arabic ascenders and descenders collide at Latin leading */
  --ln-lh: 1.45;
  /* Emphasis weights. A theme with a single emphasis weight sets both. */
  --ln-weight-strong: 600;
  --ln-weight-heavy: 700;
  /* Small group labels (section headers, table heads, legends). A theme that
     keeps every label in sentence case sets `none` and `0`. */
  --ln-label-case: uppercase;
  --ln-label-tracking: 0.04em;
}

/* The material tokens, restated wherever the depth changes so a soft subtree
   derives from its own depth rather than the root's. */
:root,
[data-ln-style='soft'] {
  /* -- Elevation ---------------------------------------------------------- */
  /* Deliberately small: depth comes from tone and edge, and the shadow is only
     the contact with the page. Blur is 2x the UIKit shadowRadius, which is how
     the two rasterisers agree. A dark page swallows a black shadow, so dark
     mode needs a heavier one to read at all. A floating layer keeps its full
     shadow at every depth, since it is the only thing separating it. */
  --ln-e-resting: 0 1px 8px light-dark(rgb(0 0 0 / calc(0.05 * var(--ln-depth))), rgb(0 0 0 / calc(0.28 * var(--ln-depth))));
  --ln-e-raised: 0 3px 20px light-dark(rgb(0 0 0 / calc(0.075 * var(--ln-depth))), rgb(0 0 0 / calc(0.4 * var(--ln-depth))));
  --ln-e-floating: 0 9px 44px light-dark(rgb(0 0 0 / 0.12), rgb(0 0 0 / 0.52));

  /* -- Surface finish ---------------------------------------------------- */
  /* The full-height tonal wash — a few percent, never a highlight sweep. In
     dark mode light gathers on the top edge; in light mode a white sheen over a
     near-white card is invisible, so the cue is occlusion gathering at the
     bottom instead. Same physics from the other side. */
  --ln-sheen: linear-gradient(
    light-dark(rgb(255 255 255 / 0), rgb(255 255 255 / calc(0.05 * var(--ln-depth)))),
    rgb(255 255 255 / 0) 45%,
    light-dark(rgb(0 0 0 / calc(0.035 * var(--ln-depth))), rgb(0 0 0 / calc(0.05 * var(--ln-depth))))
  );
  --ln-sheen-quiet: linear-gradient(
    light-dark(rgb(255 255 255 / 0), rgb(255 255 255 / calc(0.03 * var(--ln-depth)))),
    rgb(255 255 255 / 0) 45%,
    light-dark(rgb(0 0 0 / calc(0.021 * var(--ln-depth))), rgb(0 0 0 / calc(0.03 * var(--ln-depth))))
  );
  --ln-sheen-lit: linear-gradient(
    light-dark(rgb(255 255 255 / calc(0.1 * var(--ln-depth))), rgb(255 255 255 / calc(0.05 * var(--ln-depth)))),
    rgb(255 255 255 / 0) 45%,
    light-dark(rgb(0 0 0 / calc(0.07 * var(--ln-depth))), rgb(0 0 0 / calc(0.05 * var(--ln-depth))))
  );
  /* The 1px lip where the light lands. */
  --ln-lip: light-dark(rgb(255 255 255 / calc(0.75 * var(--ln-depth))), rgb(255 255 255 / calc(0.1 * var(--ln-depth))));
  --ln-lip-lit: light-dark(rgb(255 255 255 / calc(0.34 * var(--ln-depth))), rgb(255 255 255 / calc(0.26 * var(--ln-depth))));
  /* A well's shadow falls inward. It has no lip of its own — the light lands
     on the rim above it. */
  --ln-inner: inset 0 1px 6px light-dark(rgb(0 0 0 / calc(0.1 * var(--ln-depth))), rgb(0 0 0 / calc(0.34 * var(--ln-depth))));
}

[data-theme='light'] {
  color-scheme: light;
}
[data-theme='dark'] {
  color-scheme: dark;
}

/* One device pixel per speck. A 96px tile on a 3x screen is 3px blocks. */
@media (min-resolution: 2dppx) {
  :root {
    --ln-grain-size: 48px 48px;
  }
}
@media (min-resolution: 3dppx) {
  :root {
    --ln-grain-size: 32px 32px;
  }
}

/* The one rule the web needs that iOS does not: a visible keyboard focus.
   Accent, outside the box, so it reads on every surface state. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--ln-focus);
  outline-offset: 2px;
  border-radius: inherit;
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --ln-t-tap: 0.001s;
    --ln-t-move: 0.001s;
  }
}

/* ========================================================================== *
 * Canvas
 * ========================================================================== */

/* Every Lantern component is measured border-box, because several of them are
   `width: 100%` with padding and would otherwise overflow their container by
   exactly that padding — which is what happened to the gallery's rows on a page
   that had no reset of its own. Scoped to our own class prefix rather than `*`:
   nothing else in this file selects a bare element, so linking the language can
   never silently re-measure a consumer's markup. `[class^=]` plus `[class*=" "]`
   matches `ln-*` as a whole token, not as a substring of someone else's name. */
[class^='ln-'],
[class^='ln-']::before,
[class^='ln-']::after,
[class*=' ln-'],
[class*=' ln-']::before,
[class*=' ln-']::after {
  box-sizing: border-box;
}

.ln-canvas {
  min-height: 100%;
  background-color: var(--ln-canvas);
  background-image: linear-gradient(var(--ln-canvas-top), var(--ln-canvas-bottom));
  background-attachment: fixed;
  color: var(--ln-ink);
  font-family: var(--ln-font);
  font-size: var(--ln-fs-body);
  line-height: var(--ln-lh);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Browser surfaces follow the theme on every page that links the sheet, not
   only under `.ln-canvas`. Selection keeps the text's own ink; on an accent
   fill an accent tint would vanish, so a lit surface uses a wash of its ink. */
::selection {
  background: var(--ln-selection);
}
.ln-surface.ln-lit ::selection {
  background: color-mix(in srgb, var(--ln-on-accent) 30%, transparent);
}
/* `scrollbar-color` inherits, so the root covers the page; a themed subtree
   restates it so its own `light-dark()` resolves. */
:root,
[data-theme],
[data-ln-theme] {
  scrollbar-color: var(--ln-ink-tertiary) transparent;
}

/* ========================================================================== *
 * Surface — the single container primitive
 * ========================================================================== */

.ln-surface {
  position: relative;
  border-radius: var(--ln-radius, var(--ln-r-md));
  border: 1px solid var(--ln-hairline);
  background-color: var(--ln-surface);
  background-image: var(--ln-grain), var(--ln-sheen);
  background-size: var(--ln-grain-size), auto;
  background-repeat: repeat, no-repeat;
  box-shadow: var(--ln-e-raised);
  color: var(--ln-ink);
}

/* The specular lip: 1px of light caught on the top edge.
 *
 * It is an inset shadow on a full-size overlay, NOT a straight bar inset from
 * the corners. A bar has to guess how far to stop short of the arc, and on
 * anything round the guess is visibly wrong — on a circle it reads as a chord
 * floating inside the top of the shape, and on a pill its flat ends read as a
 * second, smaller shape. An inset shadow follows `border-radius: inherit`
 * exactly, so one recipe is correct for a card, a pill and a circle.
 *
 * The mask is the other half of it: a real specular highlight is brightest where
 * the surface faces the light and dies off as it turns away, so the line fades
 * out towards the sides instead of ringing the whole top edge. */
.ln-surface::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 1px 0 var(--ln-lip);
  mask-image: linear-gradient(to right, transparent, #000 22%, #000 78%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 22%, #000 78%, transparent);
  pointer-events: none;
  transition: opacity var(--ln-t-tap) var(--ln-ease);
}

/* A tinted panel with no depth of its own — for nesting inside another
   surface, where a second shadow would read as mud. */
.ln-surface.ln-quiet {
  background-color: var(--ln-surface-quiet);
  background-image: var(--ln-grain), var(--ln-sheen-quiet);
  border-color: var(--ln-hairline-faint);
  box-shadow: none;
}

/* A well content sits *in*. No grain, no lip; the shadow falls inward. */
.ln-surface.ln-sunken {
  background-color: var(--ln-well);
  background-image: none;
  border-color: var(--ln-hairline-faint);
  box-shadow: var(--ln-inner);
}
.ln-surface.ln-sunken::before {
  display: none;
}

/* An accent surface that emits. */
.ln-surface.ln-lit {
  background-color: var(--ln-accent);
  background-image: var(--ln-grain), var(--ln-sheen-lit);
  border-color: rgb(0 0 0 / 0.1);
  color: var(--ln-on-accent);
}
.ln-surface.ln-lit::before {
  box-shadow: inset 0 1px 0 var(--ln-lip-lit);
}
/* A lit surface sets its own ink above, but every type tier names `--ln-ink` on
   ITSELF, and a declaration on the element beats one inherited from its parent.
   So a heading dropped on a lit card kept the page's ink: near-black on the
   accent in light (3.92:1), and near-white on the lightened accent in dark
   (2.21:1) — which is exactly the failure `--ln-on-accent` exists to prevent.
   `:where()` contributes no specificity, so this lands at `.ln-surface.ln-lit`
   and a caller's own colour still wins. */
.ln-surface.ln-lit
  :where(
    .ln-display,
    .ln-title,
    .ln-headline,
    .ln-body,
    .ln-callout,
    .ln-caption,
    .ln-micro,
    .ln-section-header,
    .ln-gloss,
    .ln-meaning,
    .ln-ar
  ) {
  color: inherit;
}

.ln-flat {
  box-shadow: none;
}
.ln-resting {
  box-shadow: var(--ln-e-resting);
}
.ln-raised {
  box-shadow: var(--ln-e-raised);
}
.ln-floating {
  box-shadow: var(--ln-e-floating);
}

.ln-r-xs {
  --ln-radius: var(--ln-r-xs);
}
.ln-r-sm {
  --ln-radius: var(--ln-r-sm);
}
.ln-r-md {
  --ln-radius: var(--ln-r-md);
}
.ln-r-lg {
  --ln-radius: var(--ln-r-lg);
}
.ln-r-xl {
  --ln-radius: var(--ln-r-xl);
}

/* Padding inside a card. */
.ln-card {
  padding: var(--ln-lg);
}
.ln-card-lg {
  padding: var(--ln-xl);
}

/* A soft radial glow, behind an accent control so it looks like it is emitting
   rather than painted on. Reserved for a control that is genuinely the light
   source on its screen — a glow behind every primary button is what reads as
   amateur. */
.ln-bloom {
  position: relative;
  isolation: isolate;
}
.ln-bloom::after {
  content: '';
  position: absolute;
  inset: calc(var(--ln-bloom-spread, 22px) * -1);
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(
    closest-side,
    color-mix(in srgb, var(--ln-bloom-color, var(--ln-accent)) 45%, transparent),
    color-mix(in srgb, var(--ln-bloom-color, var(--ln-accent)) 15%, transparent) 55%,
    rgb(255 255 255 / 0) 100%
  );
  pointer-events: none;
  transition: opacity var(--ln-t-tap) var(--ln-ease);
}

/* ========================================================================== *
 * Type
 * ========================================================================== */

.ln-display {
  font-size: var(--ln-fs-display);
  font-weight: var(--ln-weight-heavy);
  line-height: 1.15;
  letter-spacing: -0.015em;
  color: var(--ln-ink);
  margin: 0;
}
.ln-title {
  font-size: var(--ln-fs-title);
  font-weight: var(--ln-weight-strong);
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ln-ink);
  margin: 0;
}
.ln-headline {
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
  line-height: 1.3;
  color: var(--ln-ink);
  margin: 0;
}
.ln-body {
  font-size: var(--ln-fs-body);
  line-height: var(--ln-lh);
  color: var(--ln-ink);
  margin: 0;
}
.ln-callout {
  font-size: var(--ln-fs-callout);
  line-height: 1.4;
  color: var(--ln-ink);
  margin: 0;
}
.ln-caption {
  font-size: var(--ln-fs-caption);
  line-height: 1.35;
  color: var(--ln-ink-quiet);
  margin: 0;
}
/* The smallest legible tier. */
.ln-micro {
  font-size: var(--ln-fs-micro);
  font-weight: var(--ln-weight-strong);
  line-height: 1.2;
  letter-spacing: 0.02em;
  color: var(--ln-ink-quiet);
  margin: 0;
}
/* A section title above a group. Sentence case, quiet — the content should
   carry the weight, not its label. */
.ln-section-header {
  font-size: var(--ln-fs-micro);
  font-weight: var(--ln-weight-strong);
  letter-spacing: var(--ln-label-tracking);
  text-transform: var(--ln-label-case);
  color: var(--ln-ink-quiet);
  margin: 0;
}

.ln-secondary {
  color: var(--ln-ink-secondary);
}
.ln-tertiary {
  color: var(--ln-ink-tertiary);
}
.ln-quiet-ink {
  color: var(--ln-ink-quiet);
}
.ln-accent-ink {
  color: var(--ln-accent);
}

/* A gloss / literal reading. */
.ln-gloss {
  font-style: italic;
  color: var(--ln-ink-secondary);
  margin: 0;
}
/* A translation — a serif italic reads as "this is the meaning, not the words". */
.ln-meaning {
  font-family: var(--ln-font-serif);
  font-style: italic;
  color: var(--ln-ink-secondary);
  margin: 0;
}
.ln-mono {
  font-family: var(--ln-font-mono);
  font-size: var(--ln-fs-caption);
  margin: 0;
}
/* Timers, intervals, offsets — anything whose digits must not jitter. */
/* Isolated too, so "12 US$" or "00:14" keeps its own order inside Arabic text
   and never reorders the words around it. */
.ln-digits {
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum';
  unicode-bidi: isolate;
  margin: 0;
}

/* Arabic. `direction` is the load-bearing half: right-aligning a block leaves
   the writing direction LTR, which mis-orders mixed content like "عندي 3 كتب".
   `unicode-bidi: isolate` keeps a run from reordering its neighbours. */
.ln-ar {
  font-family: var(--ln-font-ar);
  direction: rtl;
  unicode-bidi: isolate;
  text-align: right;
  line-height: var(--ln-lh-ar);
  color: var(--ln-ink);
  /* Like every Latin tier above: spacing is the stack's job, never the
     paragraph's. Without this a `<p class="ln-ar ln-ar-hero">` keeps the UA's
     1em margin — 38px on each side of every line, which a flex `gap` adds to
     rather than collapses with. */
  margin: 0;
}
.ln-ar-hero {
  font-size: var(--ln-fs-ar-hero);
  font-weight: var(--ln-weight-strong);
}
.ln-ar-title {
  font-size: var(--ln-fs-ar-title);
  font-weight: var(--ln-weight-strong);
}
.ln-ar-row {
  font-size: var(--ln-fs-ar-row);
}
.ln-ar-body {
  font-size: var(--ln-fs-ar-body);
}
.ln-ar-caption {
  font-size: var(--ln-fs-ar-caption);
}
.ln-ar.ln-center {
  text-align: center;
}
/* In a table the alignment belongs to the COLUMN and the direction to the cell.
   `.ln-ar` carries both, so an Arabic cell dropped into a table ends up flush
   right under a left-aligned `th` — which reads as a broken column, not as a
   script. The base direction is the half that matters here: it is what orders
   the content. Spelled `left` rather than `inherit` or `start`, because both of
   those resolve to the RIGHT edge once `direction: rtl` is on the cell, which is
   the whole problem. */
.ln-table .ln-ar {
  text-align: left;
}
.ln-table:dir(rtl) .ln-ar {
  text-align: right;
}

/* Prose links sit in `:where()` so they weigh one class, and skip the link-shaped
   components outright. At `.ln-prose a` (0,1,1) they outranked `.ln-btn` (0,1,0)
   and painted a button's label in accent on its own accent fill. */
a.ln-link,
.ln-prose :where(a:not(.ln-btn, .ln-icon-btn, .ln-pill, .ln-row)) {
  color: var(--ln-accent);
  text-decoration-color: color-mix(in srgb, var(--ln-accent) 40%, transparent);
  text-underline-offset: 0.2em;
}
/* A 44px hit area around a small link, without moving anything around it. */
.ln-target {
  position: relative;
}
.ln-target::after {
  content: '';
  position: absolute;
  inset-block: min(0px, calc((100% - 44px) / 2));
  inset-inline: min(0px, calc((100% - 44px) / 2));
}
a.ln-link:hover,
.ln-prose :where(a:not(.ln-btn, .ln-icon-btn, .ln-pill, .ln-row)):hover {
  text-decoration-color: var(--ln-accent);
}

/* ========================================================================== *
 * Button
 * ========================================================================== */

/* One class, six roles — so "the primary action" looks the same on every screen
   instead of being re-invented per file. A filled button is a key cut from the
   same material as everything else: a barely-there tonal gradient, a 1px
   specular lip, and a tight neutral contact shadow. Pressing it sinks it and
   dims the lip. Explicitly not: a coloured glow, or a white gloss sweeping half
   the height.

   A product can retune the finish from any ancestor without overriding rules:
   `--ln-btn-gloss` (the tonal gradient, or `none`), `--ln-btn-lip` (the 1px
   top edge colour), `--ln-btn-shadow` and `--ln-btn-border`. Each is read with
   a fallback at the button, so the default gradient still follows the
   button's own fill. */
.ln-btn {
  --ln-btn-fill: var(--ln-accent);
  --ln-btn-ink: var(--ln-on-accent);
  /* A theme sizes every button from an ancestor with `--ln-radius-button`,
     `--ln-button-height`, `--ln-button-pad-block`, `--ln-button-pad-inline`
     and `--ln-button-size`. */
  --ln-btn-radius: var(--ln-radius-button, var(--ln-radius-control, var(--ln-r-md)));
  /* Readable by a site, so a quiet button can hang its label on a column edge:
     `margin-inline-start: calc(var(--ln-btn-pad-inline) * -1)`. */
  --ln-btn-pad-inline: var(--ln-button-pad-inline, 22px);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--ln-sm);
  min-height: var(--ln-button-height, 52px);
  padding: var(--ln-button-pad-block, 14px) var(--ln-btn-pad-inline);
  border: 1px solid var(--ln-btn-border, rgb(0 0 0 / 0.12));
  border-radius: var(--ln-btn-radius);
  font-family: inherit;
  font-size: var(--ln-button-size, var(--ln-fs-headline));
  font-weight: var(--ln-weight-strong);
  line-height: 1.2;
  color: var(--ln-btn-ink);
  background-color: var(--ln-btn-fill);
  /* A few percent from top to bottom. Any more and it stops looking machined
     and starts looking moulded. */
  background-image:
    var(--ln-grain),
    var(
      --ln-btn-gloss,
      linear-gradient(
        light-dark(color-mix(in srgb, var(--ln-btn-fill), #fff calc(5.5% * var(--ln-depth))), color-mix(in srgb, var(--ln-btn-fill), #fff calc(7% * var(--ln-depth)))),
        light-dark(color-mix(in srgb, var(--ln-btn-fill), #000 calc(4.5% * var(--ln-depth))), color-mix(in srgb, var(--ln-btn-fill), #000 calc(5% * var(--ln-depth))))
      )
    );
  background-size: var(--ln-grain-size), auto;
  background-repeat: repeat, no-repeat;
  box-shadow: var(--ln-btn-shadow, var(--ln-e-raised));
  cursor: pointer;
  text-decoration: none;
  text-align: center;
  transition:
    transform var(--ln-t-tap) var(--ln-ease),
    box-shadow var(--ln-t-tap) var(--ln-ease),
    opacity var(--ln-t-tap) var(--ln-ease);
  -webkit-tap-highlight-color: transparent;
}

/* Same recipe as the surface lip — see the note there for why it is a shadow on
   an overlay rather than a bar. A pill button is exactly the case a bar breaks. */
.ln-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 1px 0 var(--ln-btn-lip, light-dark(rgb(255 255 255 / calc(0.3 * var(--ln-depth))), rgb(255 255 255 / calc(0.2 * var(--ln-depth)))));
  mask-image: linear-gradient(to right, transparent, #000 22%, #000 78%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 22%, #000 78%, transparent);
  pointer-events: none;
  transition: opacity var(--ln-t-tap) var(--ln-ease);
}

.ln-btn:active:not(:disabled) {
  transform: scale(0.985);
  box-shadow: var(--ln-e-resting);
}
.ln-btn:active:not(:disabled)::before {
  opacity: 0.2;
}
.ln-btn:active:not(:disabled) .ln-bloom::after,
.ln-btn.ln-bloom:active:not(:disabled)::after {
  opacity: 0.5;
}

/* Everything else: a chip, a toolbar action. */
.ln-btn.ln-secondary-btn {
  --ln-btn-fill: var(--ln-surface-quiet);
  --ln-btn-ink: var(--ln-ink);
  border-color: var(--ln-btn-border, var(--ln-hairline));
  background-image: var(
    --ln-btn-gloss,
    linear-gradient(
      light-dark(color-mix(in srgb, var(--ln-btn-fill), #fff calc(5.5% * var(--ln-depth))), color-mix(in srgb, var(--ln-btn-fill), #fff calc(7% * var(--ln-depth)))),
      light-dark(color-mix(in srgb, var(--ln-btn-fill), #000 calc(4.5% * var(--ln-depth))), color-mix(in srgb, var(--ln-btn-fill), #000 calc(5% * var(--ln-depth))))
    )
  );
  /* One gradient, so it spans the whole button. The base rule sizes two layers
     and the first size (the grain tile) would otherwise tile this gradient,
     leaving a seam on any button taller than the tile. */
  background-size: auto;
  background-repeat: no-repeat;
  box-shadow: var(--ln-btn-shadow, var(--ln-e-resting));
}

/* Reserved for the accent's warm counterpart (streaks, mastery). */
.ln-btn.ln-ember-btn {
  --ln-btn-fill: var(--ln-ember);
  --ln-btn-ink: var(--ln-on-ember);
}

/* A lit critical fill, for the one destructive action a screen is about. */
.ln-btn.ln-destructive {
  --ln-btn-fill: var(--ln-critical-fill);
  --ln-btn-ink: var(--ln-on-critical);
}

/* The other two thirds of the same pair. A status *fill* is for a button that
   commits to that status — "Mark as known", "Overwrite anyway" — not for a
   button that merely mentions it; that one is `.ln-quiet-btn` with the ink. */
.ln-btn.ln-positive {
  --ln-btn-fill: var(--ln-positive-fill);
  --ln-btn-ink: var(--ln-on-positive);
}
.ln-btn.ln-caution {
  --ln-btn-fill: var(--ln-caution-fill);
  --ln-btn-ink: var(--ln-on-caution);
}

/* Text only, no surface. */
.ln-btn.ln-quiet-btn,
.ln-btn.ln-quiet-destructive {
  --ln-btn-ink: var(--ln-accent);
  background: none;
  border-color: transparent;
  box-shadow: none;
  font-weight: 500;
}
.ln-btn.ln-quiet-btn::before,
.ln-btn.ln-quiet-destructive::before {
  display: none;
}
.ln-btn.ln-quiet-btn:hover:not(:disabled),
.ln-btn.ln-quiet-destructive:hover:not(:disabled) {
  background: color-mix(in srgb, currentColor 8%, transparent);
}
/* Text in the critical hue, for a destructive action that must not be the
   loudest thing on its screen: a lit red button invites the tap it is warning
   about, while the accent's blue makes "delete everything" read as an ordinary
   link. */
.ln-btn.ln-quiet-destructive {
  --ln-btn-ink: var(--ln-critical);
}

/* A chip in a row of chips. Under 44px it resolves to a true capsule. */
.ln-btn.ln-compact {
  --ln-btn-radius: var(--ln-r-pill);
  --ln-btn-pad-inline: 14px;
  min-height: 40px;
  padding: 9px var(--ln-btn-pad-inline);
  font-size: var(--ln-fs-callout);
  font-weight: 500;
}
.ln-btn.ln-compact.ln-squared {
  --ln-btn-radius: var(--ln-r-sm);
}
.ln-btn.ln-block {
  display: flex;
  width: 100%;
}

/* A disabled control is inert, not a faded version of an active one: dimming a
   lit fill leaves white text on a pale tint, the least legible thing on the
   screen. */
.ln-btn:disabled,
.ln-btn[aria-disabled='true'] {
  --ln-btn-fill: var(--ln-surface-quiet);
  --ln-btn-ink: var(--ln-ink-tertiary);
  background-image: none;
  border-color: var(--ln-hairline-faint);
  box-shadow: none;
  cursor: default;
  transform: none;
}
.ln-btn:disabled::before,
.ln-btn[aria-disabled='true']::before {
  display: none;
}
/* A quiet button stays text when disabled: a pill and fill there reads as hover. */
.ln-btn.ln-quiet-btn:is(:disabled, [aria-disabled='true']),
.ln-btn.ln-quiet-destructive:is(:disabled, [aria-disabled='true']) {
  background: none;
  border-color: transparent;
}

/* A circular symbol button: a bar action, a transport control. `ln-bare` for a
   button in bar chrome — a contact shadow is the contact between an object and
   the surface under it, and a bar button has no surface under it. */
.ln-icon-btn {
  --ln-btn-fill: var(--ln-surface-quiet);
  --ln-btn-ink: var(--ln-ink);
  --ln-icon-size: 38px;
  /* The icon box. The UIKit button builds its SF Symbol at `diameter * 0.42`;
     an `<svg>` or `<img>` handed to this one fills exactly that box (below). */
  --ln-icon-glyph: calc(var(--ln-icon-size) * 0.42);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ln-icon-size);
  height: var(--ln-icon-size);
  padding: 0;
  border: 1px solid var(--ln-btn-border, var(--ln-hairline));
  border-radius: 50%;
  color: var(--ln-btn-ink);
  background-color: var(--ln-btn-fill);
  background-image: var(
    --ln-btn-gloss,
    linear-gradient(
      light-dark(color-mix(in srgb, var(--ln-btn-fill), #fff calc(5.5% * var(--ln-depth))), color-mix(in srgb, var(--ln-btn-fill), #fff calc(7% * var(--ln-depth)))),
      light-dark(color-mix(in srgb, var(--ln-btn-fill), #000 calc(4.5% * var(--ln-depth))), color-mix(in srgb, var(--ln-btn-fill), #000 calc(5% * var(--ln-depth))))
    )
  );
  box-shadow: var(--ln-btn-shadow, var(--ln-e-resting));
  font-family: inherit;
  /* A text character is not an SF Symbol. A symbol's ink fills its point size,
     but a glyph carries side bearings and ascender room inside its em box and
     draws roughly two thirds of it — at the symbol's size a `✕` is a speck in a
     38px disc. So scale the FONT until a character lands at the icon box; a real
     icon takes the box directly. `600` is the web's half of the `.semibold` the
     UIKit symbol configuration already asks for. */
  font-size: calc(var(--ln-icon-glyph) * 1.4);
  font-weight: var(--ln-weight-strong);
  line-height: 1;
  cursor: pointer;
  transition:
    transform var(--ln-t-tap) var(--ln-ease),
    box-shadow var(--ln-t-tap) var(--ln-ease);
  -webkit-tap-highlight-color: transparent;
}
/* A circle is where the old straight-bar lip was worst: it sat as a visible
   chord across the top of the disc. As a shadow on a radius-inheriting overlay it
   is an arc, and the mask is tighter here because a circle turns away from the
   light much sooner than a rectangle does. */
.ln-icon-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 1px 0 var(--ln-btn-lip, light-dark(rgb(255 255 255 / calc(0.42 * var(--ln-depth))), rgb(255 255 255 / calc(0.18 * var(--ln-depth)))));
  mask-image: linear-gradient(to right, transparent, #000 34%, #000 66%, transparent);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 34%, #000 66%, transparent);
  pointer-events: none;
  transition: opacity var(--ln-t-tap) var(--ln-ease);
}
.ln-icon-btn.ln-primary-icon {
  --ln-btn-fill: var(--ln-accent);
  --ln-btn-ink: var(--ln-on-accent);
  border-color: rgb(0 0 0 / 0.12);
  box-shadow: var(--ln-e-raised);
}
.ln-icon-btn.ln-bare {
  --ln-btn-fill: transparent;
  background-image: none;
  border-color: transparent;
  box-shadow: none;
}
.ln-icon-btn.ln-bare::before {
  display: none;
}
.ln-icon-btn.ln-bare:hover:not(:disabled) {
  background-color: color-mix(in srgb, currentColor 8%, transparent);
}
.ln-icon-btn:active:not(:disabled) {
  transform: scale(0.92);
}
.ln-icon-btn:active:not(:disabled)::before {
  opacity: 0.2;
}
.ln-icon-btn:disabled {
  --ln-btn-fill: var(--ln-surface-quiet);
  --ln-btn-ink: var(--ln-ink-tertiary);
  background-image: none;
  box-shadow: none;
  cursor: default;
}
/* A supplied icon fills the icon box, so it is sized once here rather than at
   every call site — and it stays in step with `ln-sm` / `ln-lg`. */
.ln-icon-btn > svg,
.ln-icon-btn > img {
  display: block;
  width: var(--ln-icon-glyph);
  height: var(--ln-icon-glyph);
}

.ln-icon-btn.ln-lg {
  --ln-icon-size: 56px;
}
.ln-icon-btn.ln-sm {
  --ln-icon-size: 30px;
}

/* ========================================================================== *
 * Pill
 * ========================================================================== */

/* A badge. One implementation, four styles — it replaced seven hand-rolled
   capsules that agreed on nothing. */
.ln-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-xs);
  padding: 3px 9px;
  border: 1px solid
    color-mix(in srgb, var(--ln-pill-color, var(--ln-ink-quiet)) 42%, transparent);
  border-radius: var(--ln-r-pill);
  background: transparent;
  color: var(--ln-pill-color, var(--ln-ink-quiet));
  font-size: var(--ln-fs-micro);
  font-weight: var(--ln-weight-strong);
  line-height: 1.45;
  white-space: nowrap;
}
.ln-pill.ln-filled {
  background: var(--ln-pill-color, var(--ln-accent));
  border-color: transparent;
  color: var(--ln-on-accent);
}
.ln-pill.ln-wash {
  background: color-mix(in srgb, var(--ln-pill-color, var(--ln-accent)) 14%, transparent);
  border-color: color-mix(in srgb, var(--ln-pill-color, var(--ln-accent)) 24%, transparent);
  color: var(--ln-pill-color, var(--ln-accent));
}
/* Over video or artwork, where `filled`'s ink would flip to near-black in dark
   mode and vanish into the frame behind it. */
.ln-pill.ln-on-media {
  background: var(--ln-media-chip);
  border-color: rgb(255 255 255 / 0.16);
  color: var(--ln-on-media);
}
.ln-pill.ln-accent-pill {
  --ln-pill-color: var(--ln-accent);
}
.ln-pill.ln-positive-pill {
  --ln-pill-color: var(--ln-positive);
}
.ln-pill.ln-caution-pill {
  --ln-pill-color: var(--ln-caution);
}
.ln-pill.ln-critical-pill {
  --ln-pill-color: var(--ln-critical);
}

/* A pill you can press — a filter, a toggle chip. */
button.ln-pill,
a.ln-pill {
  min-height: 40px;
  padding: 6px 14px;
  cursor: pointer;
  font-family: inherit;
  transition:
    transform var(--ln-t-tap) var(--ln-ease),
    background-color var(--ln-t-tap) var(--ln-ease);
}
button.ln-pill:active {
  transform: scale(0.96);
}
button.ln-pill[aria-pressed='true'],
.ln-pill.ln-selected {
  background: var(--ln-accent-wash);
  border-color: color-mix(in srgb, var(--ln-accent) 34%, transparent);
  color: var(--ln-accent);
}

/* ========================================================================== *
 * Rows and groups
 * ========================================================================== */

/* A hairline between two rows of the same group. */
.ln-separator {
  height: 1px;
  border: 0;
  margin: 0;
  background: var(--ln-hairline);
}

/* A group of rows inside one raised card, hairlines between them. */
.ln-group {
  display: flex;
  flex-direction: column;
  border-radius: var(--ln-radius, var(--ln-r-md));
  overflow: hidden;
}
.ln-group > * + * {
  border-top: 1px solid var(--ln-hairline);
}

/* A tappable line in a group: an optional accent glyph, a title, a value, an
   accessory. It dims rather than sinks on press — a row is part of a card's
   surface, not an object sitting on it, so scaling it would peel it off. */
.ln-row {
  display: flex;
  align-items: center;
  gap: var(--ln-md);
  width: 100%;
  padding: var(--ln-sm) var(--ln-lg);
  border: 0;
  background: none;
  color: var(--ln-ink);
  font: inherit;
  text-align: start;
  text-decoration: none;
  transition: opacity var(--ln-t-tap) var(--ln-ease);
}
.ln-row > .ln-row-title {
  flex: 1;
  min-width: 0;
}
.ln-row > .ln-row-value {
  color: var(--ln-ink-quiet);
  font-size: var(--ln-fs-callout);
  white-space: nowrap;
}
.ln-row > .ln-row-icon {
  color: var(--ln-accent);
  flex: none;
  width: 24px;
  text-align: center;
}
.ln-row[href],
.ln-row[type],
button.ln-row {
  cursor: pointer;
}
.ln-row[href]:active,
button.ln-row:active {
  opacity: 0.55;
}
.ln-row.ln-selected {
  background: var(--ln-accent-wash);
}
/* Pushes a screen. */
/* '›' is a bidi-mirrored character, so RTL already draws it as '‹'. */
.ln-row-chevron::after {
  content: '›';
  color: var(--ln-ink-tertiary);
  font-size: 1.15em;
  line-height: 1;
}

/* A label on the leading side and its control on the trailing side. The label
   holds its width and the control yields — a label that yields instead just
   disappears, and then the row is a control with nothing saying what it does. */
.ln-control-row {
  display: flex;
  align-items: center;
  gap: var(--ln-md);
}
.ln-control-row > .ln-control-label {
  flex: none;
  color: var(--ln-ink-quiet);
  font-size: var(--ln-fs-callout);
}
.ln-control-row > :last-child {
  flex: 1;
  min-width: 0;
}
/* A segmented control never shrinks past its labels; it drops under its
   label instead of pushing the page sideways on a phone. */
.ln-control-row:has(> .ln-segmented) {
  flex-wrap: wrap;
}
.ln-control-row > .ln-segmented {
  min-width: fit-content;
}

/* ========================================================================== *
 * Fields
 * ========================================================================== */

/* Icons inherit ink and stay secondary to the visible label. */
.ln-icon {
  display: inline-block;
  width: 20px;
  height: 20px;
  flex: 0 0 20px;
  vertical-align: middle;
}
.ln-sidebar-nav {
  display: grid;
  gap: 4px;
}
/* The links carry no `ln-` class, so the border-box reset above misses them;
   without this the 44px minimum was content height and a row measured 64px. */
.ln-sidebar-nav > a,
.ln-subnav > a {
  box-sizing: border-box;
}
.ln-sidebar-nav > a {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  padding: 10px 12px;
  border-radius: var(--ln-r-xs);
  color: var(--ln-ink-secondary);
  text-decoration: none;
  font-size: var(--ln-fs-body);
}
.ln-sidebar-nav > a:hover {
  background: var(--ln-well);
  color: var(--ln-ink);
}
.ln-sidebar-nav > a[aria-current='page'] {
  background: var(--ln-accent-wash);
  color: var(--ln-accent);
  font-weight: var(--ln-weight-strong);
}

/* Local navigation is a row of destinations, not a row of raised buttons. */
.ln-subnav {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 20px;
  border-block-end: 1px solid var(--ln-hairline-faint);
}
.ln-subnav > a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-block: 8px;
  color: var(--ln-ink-secondary);
  text-decoration: none;
  border-block-end: 2px solid transparent;
}
.ln-subnav > a:hover,
.ln-subnav > a[aria-current] {
  color: var(--ln-accent);
  border-block-end-color: currentColor;
}

/* Form rhythm groups labels with controls without adding another surface. */
.ln-form {
  display: grid;
  gap: 16px;
}
.ln-field {
  display: grid;
  gap: 6px;
  min-width: 0;
}
.ln-field > label {
  font-size: var(--ln-fs-body);
  font-weight: var(--ln-weight-strong);
}
.ln-form-divider {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ln-ink-secondary);
  font-size: var(--ln-fs-micro);
}
.ln-form-divider::before,
.ln-form-divider::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--ln-hairline-faint);
}

/* Editable text in a well. */
.ln-input,
.ln-textarea,
.ln-select {
  display: block;
  width: 100%;
  padding: var(--ln-sm) var(--ln-md);
  border: 1px solid var(--ln-field-border);
  border-radius: var(--ln-radius-control, var(--ln-r-sm));
  background: var(--ln-field-fill, var(--ln-well));
  box-shadow: var(--ln-inner);
  color: var(--ln-ink);
  font-family: inherit;
  font-size: var(--ln-fs-body);
  line-height: var(--ln-lh);
  transition:
    border-color var(--ln-t-tap) var(--ln-ease),
    box-shadow var(--ln-t-tap) var(--ln-ease);
}
.ln-textarea {
  min-height: 72px;
  resize: vertical;
}
.ln-input::placeholder,
.ln-textarea::placeholder {
  color: var(--ln-ink-placeholder);
}
.ln-input:focus,
.ln-textarea:focus,
.ln-select:focus {
  outline: none;
  border-color: var(--ln-field-focus);
  box-shadow:
    var(--ln-inner),
    0 0 0 3px var(--ln-accent-wash);
}
.ln-input:disabled,
.ln-textarea:disabled,
.ln-select:disabled {
  color: var(--ln-ink-tertiary);
  cursor: default;
}
.ln-select {
  appearance: none;
  padding-inline-end: var(--ln-xxl);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ln-ink-tertiary) 50%),
    linear-gradient(135deg, var(--ln-ink-tertiary) 50%, transparent 50%);
  background-position:
    right var(--ln-lg) center,
    right var(--ln-md) center;
  background-size:
    5px 5px,
    5px 5px;
  background-repeat: no-repeat;
  cursor: pointer;
}
/* The chevron is two triangles; mirrored, they trade places. */
.ln-select:dir(rtl) {
  background-position:
    left var(--ln-md) center,
    left var(--ln-lg) center;
}
.ln-field-label {
  display: block;
  margin-bottom: var(--ln-xs);
  font-size: var(--ln-fs-micro);
  font-weight: var(--ln-weight-strong);
  letter-spacing: 0.02em;
  color: var(--ln-ink-quiet);
}
.ln-field-hint {
  margin-top: var(--ln-xs);
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
.ln-field-hint.ln-error {
  color: var(--ln-critical);
}

/* A toggle in the app's accent. */
.ln-switch {
  position: relative;
  display: inline-flex;
  flex: none;
  align-items: center;
  width: 51px;
  height: 31px;
  border-radius: var(--ln-r-pill);
  background: var(--ln-well);
  border: 1px solid var(--ln-control-edge);
  box-shadow: var(--ln-inner);
  cursor: pointer;
  transition:
    background-color var(--ln-t-move) var(--ln-ease),
    border-color var(--ln-t-move) var(--ln-ease);
  -webkit-tap-highlight-color: transparent;
}
.ln-switch > input {
  position: absolute;
  inset: 0;
  opacity: 0;
  margin: 0;
  cursor: pointer;
}
.ln-switch > .ln-switch-knob {
  position: absolute;
  inset-inline-start: 2px;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: var(--ln-switch-knob, light-dark(#fff, #f3f3f1));
  box-shadow: var(--ln-e-resting);
  transition: transform var(--ln-t-move) var(--ln-ease-spring);
  pointer-events: none;
}
.ln-switch:has(> input:checked) {
  background: var(--ln-accent);
  border-color: rgb(0 0 0 / 0.12);
  box-shadow: none;
}
.ln-switch:has(> input:checked) > .ln-switch-knob {
  transform: translateX(20px);
  /* A theme whose accent is light sets a dark knob for the on state. */
  background: var(--ln-switch-knob-on, var(--ln-switch-knob, light-dark(#fff, #f3f3f1)));
}
.ln-switch:dir(rtl):has(> input:checked) > .ln-switch-knob {
  transform: translateX(-20px);
}
.ln-switch:has(> input:focus-visible) {
  outline: 2px solid var(--ln-focus);
  outline-offset: 2px;
}
.ln-switch:has(> input:disabled) {
  opacity: 0.5;
  cursor: default;
}

/* A row of choices sunk into the surface, the selected one raised back out of
   it. Radio labels are the no-JS form; buttons are the dynamic form used when
   a page owns the state. Both stay one component so a selector does not grow a
   page-specific visual dialect. */
.ln-segmented {
  display: inline-flex;
  align-items: stretch;
  padding: 2px;
  border: 1px solid var(--ln-hairline-faint);
  /* A capsule, matching `LanternSegmentedControl`, which sets
     `Radius.capsule(bounds.height)` on its layer. The web had this at `r-xs`. */
  border-radius: var(--ln-r-pill);
  background: var(--ln-well);
  box-shadow: var(--ln-inner);
}
/* Equal widths, not width-by-content: a two-segment control whose labels are
   "Spotlight" and "Study" should not have one segment twice the other. */
.ln-segmented > label,
.ln-segmented > button {
  position: relative;
  flex: 1;
  display: inline-flex;
  box-sizing: border-box;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 8px 14px;
  border: 1px solid transparent;
  /* Concentric with the track: a capsule inside a capsule. */
  border-radius: var(--ln-r-pill);
  background: none;
  color: var(--ln-ink-quiet);
  font-family: inherit;
  font-size: var(--ln-fs-callout);
  cursor: pointer;
  text-align: center;
  white-space: nowrap;
  transition:
    background-color var(--ln-t-tap) var(--ln-ease),
    color var(--ln-t-tap) var(--ln-ease);
}
.ln-segmented > button:hover:not(:disabled),
.ln-segmented > label:hover {
  color: var(--ln-ink);
}
.ln-segmented input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
/* In dark a surface on a well is a step of a few percent, too close to tell
   apart, so the raised segment lifts toward the ink, takes the strong rule and
   catches the lip. The weight carries it without colour at all. */
.ln-segmented > label:has(input:checked),
.ln-segmented > button[aria-pressed='true'],
.ln-segmented > [role='tab'][aria-selected='true'] {
  background: light-dark(var(--ln-surface), color-mix(in srgb, var(--ln-surface-quiet), var(--ln-ink) 9%));
  border: 1px solid light-dark(var(--ln-hairline), var(--ln-hairline-strong));
  color: var(--ln-ink);
  font-weight: var(--ln-weight-strong);
  box-shadow:
    var(--ln-e-resting),
    inset 0 1px 0 light-dark(transparent, var(--ln-lip));
}
.ln-segmented > label:has(input:focus-visible) {
  outline: 2px solid var(--ln-focus);
  outline-offset: 1px;
}
.ln-segmented > button:disabled {
  color: var(--ln-ink-tertiary);
  cursor: default;
}

/* A value track: a well with a lit fill and a machined cap. */
.ln-slider {
  appearance: none;
  width: 100%;
  height: 26px;
  background: transparent;
  cursor: pointer;
}
.ln-slider::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: var(--ln-well);
  border: 1px solid var(--ln-control-edge);
  box-shadow: var(--ln-inner);
}
.ln-slider::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--ln-well);
  border: 1px solid var(--ln-control-edge);
  box-shadow: var(--ln-inner);
}
.ln-slider::-moz-range-progress {
  height: 6px;
  border-radius: 3px;
  background: var(--ln-accent);
}
/* A transport, not a setting: the part already played is lit. Gecko fills a
   range on its own (above); WebKit has no track-fill pseudo-element, so the fill
   is painted into the track and needs the value handed to it — CSS cannot read
   an input's value. Set `--ln-progress` (0…1) wherever you set `.value`. Not
   `Lantern.setProgress`: that one also writes progressbar ARIA, which would lie
   about a control the reader can drag. */
.ln-slider.ln-filled {
  --ln-progress: 0;
}
/* `no-repeat` is load-bearing. A gradient is sized to the PADDING box but
   clipped to the BORDER box, so with the default `repeat` the tile starts over
   inside the track's 1px right border — and the tile starts on the accent stop.
   The result was a blue cap welded to the right end of every filled track,
   whatever the value. */
.ln-slider.ln-filled::-webkit-slider-runnable-track {
  background: linear-gradient(
      to right,
      var(--ln-accent) 0 calc(var(--ln-progress) * 100%),
      transparent calc(var(--ln-progress) * 100%) 100%
    )
    no-repeat var(--ln-well);
}
/* A range fills from the right in RTL, so its painted fill does too. */
.ln-slider.ln-filled:dir(rtl)::-webkit-slider-runnable-track {
  background: linear-gradient(
      to left,
      var(--ln-accent) 0 calc(var(--ln-progress) * 100%),
      transparent calc(var(--ln-progress) * 100%) 100%
    )
    no-repeat var(--ln-well);
}
.ln-slider.ln-on-media {
  --ln-accent: var(--ln-on-media-accent);
}
.ln-slider.ln-on-media::-webkit-slider-runnable-track,
.ln-slider.ln-on-media::-moz-range-track {
  background-color: var(--ln-on-media-track);
  border-color: transparent;
  box-shadow: none;
}
.ln-slider::-webkit-slider-thumb {
  appearance: none;
  width: 26px;
  height: 26px;
  margin-top: -11px;
  border-radius: 50%;
  border: 1px solid var(--ln-control-edge);
  background-color: var(--ln-surface);
  background-image: linear-gradient(
    light-dark(rgb(255 255 255 / 0), rgb(255 255 255 / calc(0.08 * var(--ln-depth)))),
    light-dark(rgb(0 0 0 / calc(0.05 * var(--ln-depth))), rgb(0 0 0 / calc(0.06 * var(--ln-depth))))
  );
  box-shadow: var(--ln-e-resting);
}
.ln-slider::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border-radius: 50%;
  border: 1px solid var(--ln-control-edge);
  background: var(--ln-surface);
  box-shadow: var(--ln-e-resting);
}

/* A determinate bar: a well with a lit fill. */
.ln-progress {
  --ln-progress: 0;
  position: relative;
  height: 6px;
  border-radius: 3px;
  background: var(--ln-well);
  border: 1px solid var(--ln-hairline);
  box-shadow: var(--ln-inner);
  overflow: hidden;
}
.ln-progress > .ln-progress-fill {
  height: 100%;
  border-radius: 3px;
  /* Never narrower than its own height: a 2% sliver drawn into a capsule corner
     reads as a rendering glitch rather than as "just started". */
  min-width: 6px;
  width: calc(var(--ln-progress) * 100%);
  background-color: var(--ln-progress-tint, var(--ln-accent));
  background-image: linear-gradient(
    light-dark(color-mix(in srgb, var(--ln-progress-tint, var(--ln-accent)), #fff calc(5.5% * var(--ln-depth))), color-mix(in srgb, var(--ln-progress-tint, var(--ln-accent)), #fff calc(7% * var(--ln-depth)))),
    light-dark(color-mix(in srgb, var(--ln-progress-tint, var(--ln-accent)), #000 calc(4.5% * var(--ln-depth))), color-mix(in srgb, var(--ln-progress-tint, var(--ln-accent)), #000 calc(5% * var(--ln-depth))))
  );
  transition: width var(--ln-t-move) var(--ln-ease);
}
.ln-progress[data-progress='0'] > .ln-progress-fill {
  min-width: 0;
  width: 0;
}
/* Over video or artwork the well disappears and the neutral tokens go with it. */
.ln-progress.ln-on-media {
  --ln-accent: var(--ln-on-media-accent);
  background: var(--ln-on-media-track);
  border-color: transparent;
  box-shadow: none;
}

/* A determinate ring with its own reading in the middle, for a wait long enough
   that a bar would sit at the bottom of an otherwise empty screen. */
.ln-ring {
  --ln-progress: 0;
  --ln-ring-size: 96px;
  position: relative;
  width: var(--ln-ring-size);
  height: var(--ln-ring-size);
  border-radius: 50%;
  background: conic-gradient(var(--ln-accent) calc(var(--ln-progress) * 360deg), var(--ln-well) 0);
  display: grid;
  place-items: center;
}
.ln-ring::before {
  content: '';
  position: absolute;
  inset: 8px;
  border-radius: 50%;
  background: var(--ln-surface);
}
.ln-ring > .ln-ring-readout {
  position: relative;
  font-variant-numeric: tabular-nums;
  font-size: var(--ln-fs-title);
  font-weight: var(--ln-weight-strong);
}

/* A colour, as a tappable chip. A transparent colour and a white one both leave
   nothing to see on a light card, so the chip is always outlined and
   transparency is drawn as a checker. */
.ln-swatch {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 56px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-r-xs);
  /* A button's UA fill is grey in dark mode; the checker needs the surface under it. */
  background-color: transparent;
  /* The checker is the element's own background and the colour is a layer on top
     of it, not the reverse: an element's background paints *below* its ::before,
     so a checker in the pseudo-element would cover every opaque colour instead
     of showing through a transparent one. */
  background-image:
    linear-gradient(
      45deg,
      rgb(0 0 0 / 0.14) 25%,
      transparent 25%,
      transparent 75%,
      rgb(0 0 0 / 0.14) 75%
    ),
    linear-gradient(
      45deg,
      rgb(0 0 0 / 0.14) 25%,
      transparent 25%,
      transparent 75%,
      rgb(0 0 0 / 0.14) 75%
    );
  background-size: 8px 8px;
  background-position:
    0 0,
    4px 4px;
  cursor: pointer;
  font-size: var(--ln-fs-micro);
  color: var(--ln-ink-quiet);
  transition: transform var(--ln-t-tap) var(--ln-ease);
  overflow: hidden;
}
.ln-swatch::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--ln-swatch-color, transparent);
}
/* Above the colour layer, so the "None" label survives an opaque swatch. */
.ln-swatch > * {
  position: relative;
}
.ln-swatch:active {
  transform: scale(0.95);
}

/* ========================================================================== *
 * States — empty, loading, failure
 * ========================================================================== */

/* One vocabulary for the three states every list can be in, so that every
   failure in the app reads the same. */
.ln-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ln-sm);
  padding: var(--ln-xxl) var(--ln-lg);
  text-align: center;
  color: var(--ln-ink-quiet);
}
.ln-state > .ln-state-glyph {
  font-size: 2rem;
  line-height: 1;
  color: var(--ln-ink-tertiary);
}
.ln-state > .ln-state-title {
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
  color: var(--ln-ink);
}
.ln-state > .ln-state-detail {
  font-size: var(--ln-fs-callout);
  max-width: 34ch;
}
.ln-state.ln-failure > .ln-state-glyph {
  color: var(--ln-caution);
}

.ln-spinner {
  display: inline-block;
  width: var(--ln-spinner-size, 18px);
  height: var(--ln-spinner-size, 18px);
  border: 2px solid color-mix(in srgb, currentColor 22%, transparent);
  border-top-color: currentColor;
  border-radius: 50%;
  animation: ln-spin 0.7s linear infinite;
}
@keyframes ln-spin {
  to {
    transform: rotate(360deg);
  }
}
@media (prefers-reduced-motion: reduce) {
  .ln-spinner {
    animation-duration: 1.6s;
  }
}

/* A shape standing in for content that is on its way. */
.ln-skeleton {
  border-radius: var(--ln-r-xs);
  background: linear-gradient(
    90deg,
    var(--ln-surface-quiet) 25%,
    color-mix(in srgb, var(--ln-surface-quiet), var(--ln-ink) 5%) 37%,
    var(--ln-surface-quiet) 63%
  );
  background-size: 400% 100%;
  animation: ln-shimmer 1.4s ease-in-out infinite;
  color: transparent;
  user-select: none;
}
@keyframes ln-shimmer {
  from {
    background-position: 100% 0;
  }
  to {
    background-position: 0 0;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ln-skeleton {
    animation: none;
  }
}

/* ========================================================================== *
 * Over media
 * ========================================================================== */

/* A media tile: the dark recess fill, a continuous radius, clipped content, and
   — the load-bearing part — a hairline edge. Without it a tile disappears in
   dark mode: `--ln-media` is a hair off `--ln-canvas` by design, so a black
   rectangle on a black page has nothing to be an edge against, and a thumbnail
   that has not loaded reads as a hole in the screen rather than as a frame
   waiting for a frame. */
.ln-media-tile {
  background: var(--ln-media);
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-radius, var(--ln-r-sm));
  overflow: hidden;
}
.ln-media-tile > img,
.ln-media-tile > video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The gradient that lets text sit over media. Both stops are transparent black
   rather than one being `transparent`, for the same reason a card's sheen fades
   white into white. */
.ln-scrim {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(rgb(0 0 0 / 0), rgb(0 0 0 / 0.33) 55%, rgb(0 0 0 / 0.78));
}
.ln-on-media-ink {
  color: var(--ln-on-media);
}
.ln-on-media-ink-secondary {
  color: var(--ln-on-media-secondary);
}

/* ========================================================================== *
 * Chrome — bars, dialogs, sheets, toasts
 * ========================================================================== */

/* Scrolled-to-top is the page wash with no edge, so a card scrolling under the
   bar is the only edge on screen; scrolled-away gains the hairline the rest of
   the app separates things with. Toggle `data-scrolled` from a scroll listener. */
.ln-bar {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: var(--ln-md);
  padding: var(--ln-md) var(--ln-lg);
  background: var(--ln-glass);
  backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--ln-t-move) var(--ln-ease);
}
.ln-bar[data-scrolled='true'] {
  border-bottom-color: var(--ln-hairline);
}
.ln-bar > .ln-bar-title {
  flex: 1;
  min-width: 0;
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
}

/* A native <dialog>, in the language. */
dialog.ln-dialog {
  max-width: min(560px, calc(100vw - var(--ln-xl) * 2));
  max-height: min(80vh, 720px);
  padding: 0;
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-r-lg);
  background-color: var(--ln-surface);
  background-image: var(--ln-grain), var(--ln-sheen);
  background-size: var(--ln-grain-size), auto;
  box-shadow: var(--ln-e-floating);
  color: var(--ln-ink);
  overflow: hidden;
}
dialog.ln-dialog::backdrop {
  background: var(--ln-scrim);
  backdrop-filter: blur(3px);
}
dialog.ln-dialog[open] {
  animation: ln-dialog-in var(--ln-t-move) var(--ln-ease-spring);
}
@keyframes ln-dialog-in {
  from {
    opacity: 0;
    transform: translateY(12px) scale(0.985);
  }
}
.ln-dialog-head,
.ln-dialog-foot {
  display: flex;
  align-items: center;
  gap: var(--ln-sm);
  padding: var(--ln-md) var(--ln-lg);
}
.ln-dialog-head {
  border-bottom: 1px solid var(--ln-hairline);
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
}
.ln-dialog-head > :first-child {
  flex: 1;
}
.ln-dialog-body {
  padding: var(--ln-lg);
  overflow-y: auto;
}
.ln-dialog-foot {
  border-top: 1px solid var(--ln-hairline);
  justify-content: flex-end;
}

/* A sheet: the same surface, docked to an edge. Bottom on narrow screens,
   side on wide ones — the web's equivalent of a drawer and a rail being the
   same component in two places. */
dialog.ln-sheet {
  max-width: none;
  width: min(420px, 100vw);
  max-height: 100vh;
  height: 100vh;
  margin: 0;
  margin-inline-start: auto;
  border-radius: 0;
  border-start-start-radius: var(--ln-r-lg);
  border-end-start-radius: var(--ln-r-lg);
}
dialog.ln-sheet[open] {
  animation: ln-sheet-in var(--ln-t-move) var(--ln-ease);
}
@keyframes ln-sheet-in {
  from {
    transform: translateX(var(--ln-sheet-from, 24px));
    opacity: 0;
  }
}
dialog.ln-sheet:dir(rtl) {
  --ln-sheet-from: -24px;
}
@media (max-width: 560px) {
  /* `fit-content`, not `auto`: a modal dialog is inset on every side, so an
     auto height stretched the sheet to its max-height whatever it held. */
  dialog.ln-sheet {
    width: 100vw;
    height: fit-content;
    max-height: 88vh;
    margin: auto 0 0;
    border-radius: var(--ln-r-lg) var(--ln-r-lg) 0 0;
  }
  dialog.ln-sheet[open] {
    animation: ln-sheet-up var(--ln-t-move) var(--ln-ease);
  }
  @keyframes ln-sheet-up {
    from {
      transform: translateY(24px);
      opacity: 0;
    }
  }
}
/* The grab handle a bottom sheet needs to look draggable. */
.ln-sheet-grip {
  width: 36px;
  height: 4px;
  margin: var(--ln-sm) auto 0;
  border-radius: var(--ln-r-pill);
  background: var(--ln-ink-tertiary);
}

/* A transient message over the content. A toast states something and leaves. */
/* `--ln-toast-offset` lifts the stack above a sticky bottom bar. */
/* Spans the viewport rather than sitting at `left: 50%`, which left a toast
   half the screen to wrap in. It takes no pointer events itself. */
.ln-toast-host {
  position: fixed;
  inset-inline: 0;
  bottom: calc(var(--ln-xl) + var(--ln-toast-offset, 0px));
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ln-sm);
  padding-inline: var(--ln-md);
  pointer-events: none;
}
.ln-toast {
  max-width: min(88vw, 420px);
  padding: 10px 18px;
  border: 1px solid var(--ln-hairline);
  border-radius: 18px;
  background-color: var(--ln-surface);
  background-image: var(--ln-grain), var(--ln-sheen);
  background-size: var(--ln-grain-size), auto;
  box-shadow: var(--ln-e-floating);
  color: var(--ln-ink);
  font-size: var(--ln-fs-callout);
  text-align: center;
  animation: ln-toast-in var(--ln-t-move) var(--ln-ease-spring);
}
.ln-toast.ln-leaving {
  animation: ln-toast-out 0.24s var(--ln-ease) forwards;
}
.ln-toast.ln-positive-toast {
  color: var(--ln-positive);
}
.ln-toast.ln-warning-toast {
  color: var(--ln-caution);
}
.ln-toast.ln-critical-toast {
  color: light-dark(color-mix(in srgb, var(--ln-critical), var(--ln-ink) 20%), var(--ln-critical));
}
/* A toast that waits for the reader: it carries an action and a close button,
   so it takes pointer events the host itself refuses. For payment and quota
   errors, which must not vanish before they are read. */
.ln-toast.ln-persistent {
  display: flex;
  align-items: center;
  gap: var(--ln-sm);
  padding-block: 6px;
  padding-inline: 18px 6px;
  text-align: start;
  pointer-events: auto;
}
.ln-toast.ln-persistent > .ln-toast-message {
  flex: 1;
  min-width: 0;
}
.ln-toast.ln-persistent > .ln-btn {
  flex: none;
  min-height: 44px;
}
.ln-toast.ln-persistent > .ln-icon-btn {
  --ln-icon-size: 44px;
  --ln-icon-glyph: 13px;
  flex: none;
  color: var(--ln-ink-quiet);
}
@keyframes ln-toast-in {
  from {
    opacity: 0;
    transform: translateY(12px);
  }
}
@keyframes ln-toast-out {
  to {
    opacity: 0;
    transform: translateY(8px);
  }
}

/* A snackbar is an offer, not a statement: it carries up to two actions, so it
   waits long enough to read and stays reachable. A floating raised surface with
   ink on it, not a dark bar — a bar in its own palette is a second material on
   the page. */
.ln-snackbar {
  position: fixed;
  inset-inline: var(--ln-md);
  bottom: var(--ln-md);
  z-index: 100;
  max-width: 520px;
  margin: 0 auto;
  padding: var(--ln-lg);
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-r-md);
  background-color: var(--ln-surface);
  background-image: var(--ln-grain), var(--ln-sheen);
  background-size: var(--ln-grain-size), auto;
  box-shadow: var(--ln-e-floating);
  animation: ln-toast-in var(--ln-t-move) var(--ln-ease-spring);
}
.ln-snackbar > .ln-snackbar-message {
  font-size: var(--ln-fs-callout);
  color: var(--ln-ink);
}
/* Stacked, not side by side: a term, an arrow, its replacement and two verbs
   never fit one line at a large text size. */
.ln-snackbar > .ln-snackbar-actions {
  display: flex;
  gap: var(--ln-sm);
  margin-top: var(--ln-sm);
}

/* A banner that stays: a persistent, dismissible notice at the top of a view. */
.ln-banner {
  display: flex;
  align-items: center;
  gap: var(--ln-sm);
  padding: var(--ln-sm) var(--ln-md);
  border: 1px solid color-mix(in srgb, var(--ln-banner-color, var(--ln-caution)) 30%, transparent);
  border-radius: var(--ln-r-sm);
  background: color-mix(in srgb, var(--ln-banner-color, var(--ln-caution)) 12%, transparent);
  color: var(--ln-banner-color, var(--ln-caution));
  font-size: var(--ln-fs-callout);
}
.ln-banner.ln-positive-banner {
  --ln-banner-color: var(--ln-positive);
}
/* The critical hue on its own wash measures 4.0:1 in light; 30% of ink
   brings it past 4.5:1 without turning it brown. */
.ln-banner.ln-critical-banner {
  --ln-banner-color: var(--ln-critical);
  color: color-mix(in srgb, var(--ln-critical), var(--ln-ink) 30%);
}
/* Grey text in a grey wash read as a disabled field (3.65:1). Neutral is ink
   on the quiet surface, edged like one. */
.ln-banner.ln-neutral-banner {
  --ln-banner-color: var(--ln-ink-secondary);
  background: var(--ln-surface-quiet);
  border-color: var(--ln-hairline-strong);
  color: var(--ln-ink);
}
.ln-banner > :first-child {
  flex: 1;
}

/* A tooltip on hover/focus, from a `data-ln-tip` attribute. Web-only: there is
   no hover on iOS, so the language gains this one rather than porting it. */
[data-ln-tip] {
  position: relative;
}
[data-ln-tip]:hover::after,
[data-ln-tip]:focus-visible::after {
  content: attr(data-ln-tip);
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%);
  z-index: 30;
  padding: 4px 8px;
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-r-xs);
  background: var(--ln-surface);
  box-shadow: var(--ln-e-resting);
  color: var(--ln-ink);
  font-size: var(--ln-fs-micro);
  font-weight: 500;
  white-space: nowrap;
  pointer-events: none;
}

/* ========================================================================== *
 * Lists, tables, prose — web surfaces iOS has no equivalent for
 * ========================================================================== */

/* A list with no background of its own: the page wash is already behind it. */
.ln-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.ln-list > li + li {
  border-top: 1px solid var(--ln-hairline);
}

/* Plain data without a raised surface per row: quiet headers on a well,
   hairline row separators. */
.ln-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--ln-fs-callout);
  font-variant-numeric: tabular-nums;
  text-align: start;
}
.ln-table th,
.ln-table td {
  padding: var(--ln-sm) var(--ln-md);
  vertical-align: top;
  text-align: start;
}
.ln-table th {
  border-block-end: 1px solid var(--ln-hairline);
  background: var(--ln-table-head-fill, var(--ln-well));
  font-size: var(--ln-fs-micro);
  font-weight: var(--ln-weight-strong);
  letter-spacing: var(--ln-label-tracking);
  text-transform: var(--ln-label-case);
  color: var(--ln-ink-quiet);
}
.ln-table td {
  border-block-end: 1px solid var(--ln-hairline-faint);
}
.ln-table tbody tr:last-child td {
  border-block-end: 0;
}
/* Wide content scrolls inside its own box; the page never scrolls sideways. */
.ln-scroll-x {
  overflow-x: auto;
  overscroll-behavior-x: contain;
}

.ln-prose {
  color: var(--ln-ink);
  line-height: 1.6;
}
.ln-prose h1 {
  font-size: var(--ln-fs-display);
  font-weight: var(--ln-weight-heavy);
  line-height: 1.15;
  margin: 0 0 var(--ln-lg);
}
/* Headings lead tighter than the 1.6 body they sit in. */
.ln-prose h2 {
  font-size: var(--ln-fs-title);
  font-weight: var(--ln-weight-strong);
  line-height: 1.25;
  margin: var(--ln-xl) 0 var(--ln-sm);
}
.ln-prose h3 {
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
  line-height: 1.25;
  margin: var(--ln-lg) 0 var(--ln-xs);
}
.ln-prose p {
  margin: 0 0 var(--ln-md);
}
.ln-prose code {
  font-family: var(--ln-font-mono);
  font-size: 0.9em;
  padding: 1px 5px;
  border-radius: 5px;
  background: var(--ln-well);
  border: 1px solid var(--ln-hairline-faint);
}
.ln-prose pre {
  padding: var(--ln-md);
  border-radius: var(--ln-r-sm);
  background: var(--ln-well);
  border: 1px solid var(--ln-hairline-faint);
  box-shadow: var(--ln-inner);
  overflow-x: auto;
}
.ln-prose pre code {
  padding: 0;
  border: 0;
  background: none;
}

/* A search hit. */
mark.ln-mark,
.ln-prose mark {
  padding: 0 1px;
  border-radius: 3px;
  background: var(--ln-highlight);
  color: inherit;
}

/* A collapsible section. The marker is ours: the system triangle is a fifth
   grey nobody chose. */
details.ln-details > summary {
  display: flex;
  align-items: center;
  gap: var(--ln-sm);
  padding: var(--ln-sm) 0;
  cursor: pointer;
  list-style: none;
  font-size: var(--ln-fs-callout);
  font-weight: var(--ln-weight-strong);
  color: var(--ln-ink);
}
details.ln-details > summary::-webkit-details-marker {
  display: none;
}
/* A drawn chevron rather than a '›' glyph: a glyph's size, weight and bidi
   mirroring depend on the font, and a native marker points the wrong way in
   RTL in some engines. Two edges of a box, turned to point at the inline end
   while closed and down while open, so it mirrors with the direction.
   `.ln-chevron` is the same mark as an element, for a site's own summary or
   row: inside an open `<details>` summary it turns down too. */
.ln-chevron,
details.ln-details > summary::before,
details.ln-disclosure > summary::after {
  content: '';
  display: inline-block;
  flex: none;
  width: 0.42em;
  height: 0.42em;
  margin-inline: 0.12em 0.2em;
  border-style: solid;
  border-color: currentColor;
  border-width: 0 0.11em 0.11em 0;
  border-radius: 0 0 1px 0;
  transform: translateX(-0.06em) rotate(-45deg);
  transition: transform var(--ln-t-tap) var(--ln-ease);
}
.ln-chevron:dir(rtl),
details.ln-details:dir(rtl) > summary::before,
details.ln-disclosure:dir(rtl) > summary::after {
  transform: translateX(0.06em) rotate(135deg);
}
details[open] > summary .ln-chevron,
details.ln-details[open] > summary::before,
details.ln-disclosure[open] > summary::after {
  transform: translateY(-0.12em) rotate(45deg);
}
details.ln-details > summary::before {
  color: var(--ln-ink-tertiary);
}

/* ========================================================================== *
 * Product components — uploads, choices, quotas, plans, onboarding
 * ========================================================================== */

/* A drop zone: a well you put files into. Dashed because it is an invitation,
   not a surface; solid and lit once something is actually over it. */
.ln-drop {
  --ln-drop-radius: var(--ln-r-xl);
  --ln-drop-pad: clamp(48px, 9vw, 88px);
  --ln-drop-pad-compact: var(--ln-lg);
  --ln-drop-border: color-mix(in srgb, var(--ln-accent) 42%, var(--ln-hairline-strong));
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--ln-sm);
  padding: var(--ln-drop-pad) var(--ln-lg);
  border: 1.5px dashed var(--ln-drop-border);
  border-radius: var(--ln-drop-radius);
  background: var(--ln-well);
  box-shadow: var(--ln-inner);
  color: var(--ln-ink);
  text-align: center;
  transition:
    border-color var(--ln-t-tap) var(--ln-ease),
    background-color var(--ln-t-tap) var(--ln-ease),
    box-shadow var(--ln-t-tap) var(--ln-ease);
}
.ln-drop[data-over] {
  border-style: solid;
  border-color: var(--ln-accent);
  background: color-mix(in srgb, var(--ln-accent) 9%, var(--ln-well));
  box-shadow:
    var(--ln-inner),
    0 0 0 4px var(--ln-accent-wash);
}
.ln-drop[data-reject] {
  border-color: var(--ln-critical);
  background: color-mix(in srgb, var(--ln-critical) 7%, var(--ln-well));
}
.ln-drop:has(input:focus-visible) {
  outline: 2px solid var(--ln-focus);
  outline-offset: 3px;
}
.ln-drop[aria-disabled='true'] {
  opacity: 0.55;
  pointer-events: none;
}
.ln-drop > .ln-drop-glyph {
  width: 40px;
  height: 40px;
  color: var(--ln-accent);
}
.ln-drop > .ln-drop-title {
  margin: 0;
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
}
.ln-drop > .ln-drop-hint {
  margin: 0;
  max-width: 44ch;
  font-size: var(--ln-fs-callout);
  color: var(--ln-ink-quiet);
}
.ln-drop > .ln-drop-meta {
  margin: 0;
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
/* Once files are listed the zone steps aside into one row. */
.ln-drop.ln-compact {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: var(--ln-sm) var(--ln-md);
  padding: var(--ln-drop-pad-compact);
  border-radius: var(--ln-r-md);
  text-align: start;
}
.ln-drop.ln-compact > .ln-drop-glyph {
  width: 24px;
  height: 24px;
}
.ln-drop.ln-compact > .ln-drop-title {
  flex: 1;
  min-width: 12ch;
  font-size: var(--ln-fs-callout);
}

/* A full-window target while a file is dragged anywhere over the page: a
   drop works everywhere, so the feedback covers everything. Holds a
   `.ln-drop-title` and an optional `.ln-drop-hint`. */
.ln-drop-overlay {
  position: fixed;
  inset: 12px;
  z-index: 90;
  display: grid;
  place-content: center;
  gap: var(--ln-xs);
  padding: var(--ln-xl);
  border: 2px dashed var(--ln-accent);
  border-radius: var(--ln-r-md);
  background: color-mix(in srgb, var(--ln-canvas) 94%, transparent);
  text-align: center;
  pointer-events: none;
}
.ln-drop-overlay[hidden] {
  display: none;
}
.ln-drop-overlay > * {
  margin: 0;
}
.ln-drop-overlay > .ln-drop-title {
  color: var(--ln-accent);
  font-size: var(--ln-fs-title);
  font-weight: var(--ln-weight-strong);
}
.ln-drop-overlay > .ln-drop-hint {
  color: var(--ln-ink-secondary);
}

/* A file or job in a list: name, status, optional progress, meta, actions.
   The status carries the state in words as well as colour. */
.ln-file-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
/* A page rule like `:lang(ar) ol { list-style-type: arabic-indic }` outranks a
   bare class, but an item's own declaration always beats an inherited one. */
:is(.ln-steps, .ln-file-list, .ln-meter-list) > li {
  list-style: none;
}
.ln-file-list > li + li {
  border-block-start: 1px solid var(--ln-hairline);
}
.ln-file-row {
  --ln-file-tint: var(--ln-ink-quiet);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--ln-xs) var(--ln-md);
  padding: var(--ln-md) var(--ln-lg);
}
.ln-file-row[data-state='uploading'],
.ln-file-row[data-state='running'] {
  --ln-file-tint: var(--ln-accent);
}
.ln-file-row[data-state='done'],
.ln-file-row[data-state='ready'] {
  --ln-file-tint: var(--ln-positive);
}
.ln-file-row[data-state='failed'] {
  --ln-file-tint: light-dark(color-mix(in srgb, var(--ln-critical), var(--ln-ink) 20%), var(--ln-critical));
}
.ln-file-row > * {
  grid-column: 1;
  min-width: 0;
}
.ln-file-row > .ln-file-name {
  overflow: hidden;
  font-weight: var(--ln-weight-strong);
  text-overflow: ellipsis;
  white-space: nowrap;
  /* A Latin name on an Arabic page keeps its own start, so it loses its end
     to the ellipsis rather than its beginning; it still aligns with the row. */
  unicode-bidi: plaintext;
}
/* Aligned with the row, not with the name's own direction; `match-parent`
   resolves against the name in Chrome. */
.ln-file-row:dir(ltr) > .ln-file-name {
  text-align: left;
}
.ln-file-row:dir(rtl) > .ln-file-name {
  text-align: right;
}
.ln-file-row > .ln-file-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--ln-file-tint);
  font-size: var(--ln-fs-callout);
  font-weight: 500;
}
.ln-file-row > .ln-file-status::before {
  content: '';
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: currentColor;
}
.ln-file-row:is([data-state='waiting'], [data-state='queued']) > .ln-file-status::before {
  background: none;
  box-shadow: inset 0 0 0 1.5px currentColor;
}
.ln-file-row:is([data-state='uploading'], [data-state='running']) > .ln-file-status::before {
  animation: ln-pulse 1.4s var(--ln-ease) infinite;
}
.ln-file-row > .ln-file-reason {
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
.ln-file-row > .ln-file-meta {
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
.ln-file-row > .ln-progress {
  grid-column: 1 / -1;
  --ln-progress-tint: var(--ln-file-tint);
}
.ln-file-row:is([data-state='waiting'], [data-state='queued']) > .ln-progress {
  --ln-progress-tint: var(--ln-ink-tertiary);
}
.ln-file-row > .ln-file-actions {
  grid-column: 2;
  grid-row: 1 / span 2;
  display: flex;
  align-items: center;
  gap: var(--ln-xs);
}
.ln-file-row.ln-compact {
  padding: var(--ln-sm) var(--ln-md);
}
/* On a phone the actions take their own row, kept on one line at the end. */
@media (max-width: 640px) {
  .ln-file-row > .ln-file-actions {
    grid-column: 1 / -1;
    grid-row: auto;
    justify-content: flex-end;
    flex-wrap: nowrap;
  }
}
@keyframes ln-pulse {
  50% {
    opacity: 0.35;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ln-file-row > .ln-file-status::before {
    animation: none !important;
  }
}

/* A file picked but not yet sent: a chip with its name and a remove button. */
.ln-file-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-sm);
  max-width: 100%;
  min-height: 40px;
  padding-block: 4px;
  padding-inline: var(--ln-md) 4px;
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-r-pill);
  background: var(--ln-surface-quiet);
  font-size: var(--ln-fs-callout);
}
.ln-file-chip > .ln-file-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  unicode-bidi: plaintext;
}
.ln-file-chip > .ln-file-meta {
  flex: none;
  color: var(--ln-ink-quiet);
  font-size: var(--ln-fs-caption);
}
.ln-file-chip > .ln-icon-btn {
  --ln-icon-size: 32px;
  flex: none;
}

/* A choice as a card: a radio or checkbox, a title and a line of detail. The
   whole card is the label, so the hit area is the card. */
.ln-choice-group {
  display: grid;
  gap: var(--ln-sm);
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
}
.ln-choice-group > legend {
  float: inline-start;
  width: 100%;
  margin-block-end: var(--ln-sm);
  padding: 0;
  font-size: var(--ln-fs-micro);
  font-weight: var(--ln-weight-strong);
  letter-spacing: var(--ln-label-tracking);
  text-transform: var(--ln-label-case);
  color: var(--ln-ink-quiet);
}
/* Flex rather than an auto-fit grid: the floated legend is an item too, and a
   spanning item keeps auto-fit from collapsing the empty tracks. */
.ln-choice-group.ln-columns {
  display: flex;
  flex-wrap: wrap;
}
.ln-choice-group.ln-columns > .ln-choice {
  flex: 1 1 220px;
}
.ln-choice {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: start;
  gap: var(--ln-xs) var(--ln-md);
  min-height: 44px;
  padding: var(--ln-md) var(--ln-lg);
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-r-md);
  background: var(--ln-surface);
  box-shadow: var(--ln-e-resting);
  color: var(--ln-ink);
  cursor: pointer;
  transition:
    border-color var(--ln-t-tap) var(--ln-ease),
    background-color var(--ln-t-tap) var(--ln-ease);
  -webkit-tap-highlight-color: transparent;
}
.ln-choice:hover {
  border-color: var(--ln-hairline-strong);
}
.ln-choice > input {
  width: 20px;
  height: 20px;
  margin: 2px 0 0;
  accent-color: var(--ln-accent);
  cursor: pointer;
}
.ln-choice > input:focus-visible {
  outline: none;
}
.ln-choice > .ln-choice-body {
  display: grid;
  gap: var(--ln-hair);
  min-width: 0;
}
.ln-choice .ln-choice-title {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ln-xs) var(--ln-sm);
  font-weight: var(--ln-weight-strong);
}
.ln-choice .ln-choice-detail {
  font-size: var(--ln-fs-callout);
  color: var(--ln-ink-quiet);
}
.ln-choice:has(> input:checked) {
  border-color: color-mix(in srgb, var(--ln-accent) 60%, transparent);
  background: color-mix(in srgb, var(--ln-accent) 7%, var(--ln-surface));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--ln-accent) 60%, transparent);
}
.ln-choice:has(> input:focus-visible) {
  outline: 2px solid var(--ln-focus);
  outline-offset: 2px;
}
.ln-choice:has(> input:disabled) {
  opacity: 0.55;
  cursor: default;
  box-shadow: none;
}
/* An action card: the same shape as a button or link, for "ways in" on a
   first run. No input; the title takes the accent. */
a.ln-choice,
button.ln-choice {
  grid-template-columns: minmax(0, 1fr) auto;
  font: inherit;
  text-align: start;
  text-decoration: none;
}
a.ln-choice:hover,
button.ln-choice:hover {
  border-color: var(--ln-accent);
}
:is(a, button).ln-choice .ln-choice-title {
  color: var(--ln-accent);
}
:is(a, button).ln-choice > .ln-choice-body {
  grid-column: 1;
}

/* An offer: the same card with a price at the end and room for a badge. */
.ln-choice.ln-offer {
  align-items: center;
  padding-block: var(--ln-lg);
}
.ln-choice.ln-offer > input {
  margin: 0;
}
.ln-choice > .ln-choice-price {
  align-self: center;
  font-size: var(--ln-fs-title);
  font-weight: var(--ln-weight-heavy);
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
  white-space: nowrap;
}
.ln-choice .ln-choice-badge {
  font-weight: var(--ln-weight-strong);
}
@media (max-width: 480px) {
  .ln-choice > .ln-choice-price {
    grid-column: 2;
    justify-self: start;
    font-size: var(--ln-fs-headline);
  }
}

/* A quota or allowance: a label, a reading and a bar. `--ln-meter` is the
   used share of the cap (0…1). With `data-over`, `--ln-meter-need` (the
   request over the cap, above 1) widens the scale and the part past the cap is
   drawn hatched in the critical hue. `Lantern.setMeter` sets all of it. */
.ln-meter {
  --ln-meter: 0;
  --ln-meter-scale: 1;
  --ln-meter-tint: var(--ln-accent);
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: var(--ln-xs) var(--ln-md);
}
.ln-meter[data-over] {
  --ln-meter-scale: max(1, var(--ln-meter-need, 1));
}
.ln-meter[data-tone='caution'] {
  --ln-meter-tint: var(--ln-caution);
}
.ln-meter[data-tone='critical'] {
  --ln-meter-tint: var(--ln-critical);
}
.ln-meter > .ln-meter-label {
  font-size: var(--ln-fs-callout);
  font-weight: var(--ln-weight-strong);
}
.ln-meter > .ln-meter-value {
  font-size: var(--ln-fs-callout);
  color: var(--ln-ink-quiet);
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
  white-space: nowrap;
}
.ln-meter > .ln-meter-bar {
  position: relative;
  grid-column: 1 / -1;
  height: 8px;
  border: 1px solid var(--ln-hairline);
  border-radius: 4px;
  background: var(--ln-well);
  box-shadow: var(--ln-inner);
  overflow: hidden;
}
.ln-meter-bar > .ln-meter-fill {
  display: block;
  height: 100%;
  width: calc(min(1, var(--ln-meter)) / var(--ln-meter-scale) * 100%);
  border-radius: 4px;
  background: var(--ln-meter-tint);
  transition: width var(--ln-t-move) var(--ln-ease);
}
.ln-meter-bar > .ln-meter-over {
  display: none;
}
.ln-meter[data-over] .ln-meter-over {
  display: block;
  position: absolute;
  inset-block: 0;
  inset-inline-start: calc(100% / var(--ln-meter-scale));
  inset-inline-end: 0;
  border-inline-start: 2px solid var(--ln-surface);
  background: repeating-linear-gradient(
    135deg,
    color-mix(in srgb, var(--ln-critical) 70%, transparent) 0 3px,
    color-mix(in srgb, var(--ln-critical) 22%, transparent) 3px 6px
  );
}
.ln-meter > .ln-meter-text {
  grid-column: 1 / -1;
  margin: 0;
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}

/* Recording: a live dot beside a running time, and an input level. */
.ln-live {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-sm);
  color: var(--ln-live);
  font-weight: var(--ln-weight-strong);
  font-variant-numeric: tabular-nums;
}
/* The dot also stands alone, beside a label in the page's own ink. */
.ln-live-dot {
  display: inline-block;
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ln-live);
  animation: ln-pulse 1.2s ease-in-out infinite;
}
.ln-live > :not(.ln-live-dot) {
  unicode-bidi: isolate;
}
.ln-level {
  --ln-level: 0;
  position: relative;
  height: 8px;
  border-radius: var(--ln-r-pill);
  background: color-mix(in srgb, var(--ln-ink) 12%, transparent);
  overflow: hidden;
}
.ln-level::before {
  content: '';
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  width: calc(var(--ln-level) * 100%);
  border-radius: inherit;
  background: var(--ln-positive);
  transition: width 0.1s linear;
}
@media (prefers-reduced-motion: reduce) {
  .ln-live-dot {
    animation: none;
  }
}

/* A site header: brand, destinations, then actions at the inline end. Below
   720px, or wherever the links don't fit, the destinations move into a sheet
   behind a menu button (`Lantern.barMenu`), so the row never wraps. */
.ln-bar.ln-site {
  gap: var(--ln-lg);
  min-height: 64px;
  padding-block: var(--ln-sm);
}
.ln-bar > .ln-bar-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-sm);
  min-height: 44px;
  color: var(--ln-ink);
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-heavy);
  text-decoration: none;
  white-space: nowrap;
}
.ln-bar > .ln-bar-nav {
  display: flex;
  align-items: center;
  gap: 2px;
  min-width: 0;
}
.ln-bar-nav > a,
.ln-sheet-nav > a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding-inline: var(--ln-md);
  border-radius: var(--ln-r-pill);
  color: var(--ln-ink-quiet);
  font-size: var(--ln-fs-callout);
  font-weight: 500;
  text-decoration: none;
  white-space: nowrap;
  transition:
    background-color var(--ln-t-tap) var(--ln-ease),
    color var(--ln-t-tap) var(--ln-ease);
}
.ln-bar-nav > a:hover,
.ln-sheet-nav > a:hover {
  color: var(--ln-ink);
  background: color-mix(in srgb, var(--ln-ink) 6%, transparent);
}
.ln-bar-nav > a[aria-current],
.ln-sheet-nav > a[aria-current] {
  color: var(--ln-accent);
  background: var(--ln-accent-wash);
  font-weight: var(--ln-weight-strong);
}
.ln-bar-brand > .ln-bar-brand-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}
.ln-bar-brand > :is(svg, img) {
  flex: none;
}
/* The one primary destination, filled, so the phone sheet carries it with the
   other links. In the sheet it is an ordinary row. */
.ln-bar-nav > a.ln-bar-cta,
.ln-bar-nav > a.ln-bar-cta[aria-current] {
  margin-inline-start: var(--ln-xs);
  background: var(--ln-accent);
  color: var(--ln-on-accent);
  font-weight: var(--ln-weight-strong);
}
.ln-bar-nav > a.ln-bar-cta:hover {
  background: color-mix(in srgb, var(--ln-accent), var(--ln-ink) 12%);
  color: var(--ln-on-accent);
}
.ln-bar-nav > a.ln-bar-cta:active {
  background: color-mix(in srgb, var(--ln-accent), var(--ln-ink) 22%);
}
/* A secondary item in the nav, such as the language switch: set apart by a
   hairline so it doesn't read as another destination. */
.ln-bar-nav > .ln-bar-aside {
  position: relative;
  margin-inline-start: var(--ln-md);
  font-weight: 400;
}
.ln-bar-nav > .ln-bar-aside:not(.ln-bar-aside + .ln-bar-aside)::before {
  content: '';
  position: absolute;
  inset-inline-start: calc(var(--ln-md) / -2 - 0.5px);
  top: 50%;
  width: 1px;
  height: 1.1em;
  translate: 0 -50%;
  background: var(--ln-hairline-strong);
}
.ln-bar > .ln-bar-actions {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--ln-sm);
  margin-inline-start: auto;
}
.ln-bar > .ln-bar-menu {
  display: none;
  flex: none;
  --ln-icon-size: 44px;
}
/* An icon action in the bar (a theme toggle) is bar chrome like the menu
   button beside it: flat, the same weight, with no contact shadow, because
   nothing sits under it. Drawn at 40px; the hit area stays 44px. Zero extra
   specificity beyond `.ln-icon-btn.ln-bare`, so a site rule still wins. */
:where(.ln-bar > .ln-bar-actions) > .ln-icon-btn:not(.ln-primary-icon) {
  --ln-icon-size: 40px;
  --ln-btn-fill: transparent;
  background-image: none;
  border-color: transparent;
  box-shadow: none;
}
:where(.ln-bar > .ln-bar-actions) > .ln-icon-btn:not(.ln-primary-icon)::before {
  display: none;
}
:where(.ln-bar > .ln-bar-actions) > .ln-icon-btn:not(.ln-primary-icon, .ln-bloom)::after {
  content: '';
  position: absolute;
  inset: -2px;
}
:where(.ln-bar > .ln-bar-actions) > .ln-icon-btn:not(.ln-primary-icon, :disabled):hover {
  background-color: color-mix(in srgb, currentColor 8%, transparent);
}
.ln-sheet-nav {
  display: grid;
  gap: 2px;
}
.ln-sheet-nav > a {
  min-height: 48px;
  padding-inline: var(--ln-lg);
  border-radius: var(--ln-r-sm);
  font-size: var(--ln-fs-body);
}
.ln-sheet-nav > .ln-separator {
  margin: var(--ln-sm) 0;
}
/* Bar actions carried into the sheet by `Lantern.barMenu`. */
.ln-sheet-nav > .ln-sheet-actions {
  display: grid;
  gap: var(--ln-sm);
}
.ln-sheet-actions[hidden],
.ln-sheet-actions > [hidden] {
  display: none;
}
@media (max-width: 720px) {
  .ln-bar.ln-site > .ln-bar-nav {
    display: none;
  }
  .ln-bar.ln-site > .ln-bar-menu {
    display: inline-flex;
  }
  /* Only once `Lantern.barMenu` has copied them into the sheet. */
  .ln-bar.ln-site[data-ln-bar-menu] > .ln-bar-actions [data-ln-sheet] {
    display: none;
  }
}
/* Set by `Lantern.barMenu` when the links don't fit at a wider width. */
.ln-bar.ln-site[data-ln-bar-collapsed] > .ln-bar-nav {
  display: none;
}
.ln-bar.ln-site[data-ln-bar-collapsed] > .ln-bar-menu {
  display: inline-flex;
}
.ln-bar.ln-site[data-ln-bar-collapsed][data-ln-bar-menu] > .ln-bar-actions [data-ln-sheet] {
  display: none;
}
/* A 320px phone: brand, one action, theme and the menu button have to fit. */
@media (max-width: 400px) {
  .ln-bar.ln-site {
    gap: var(--ln-xs);
    padding-inline: var(--ln-md);
  }
  .ln-bar.ln-site > .ln-bar-actions {
    gap: var(--ln-xs);
  }
  /* The brand gives way last, and only here: its name ellipsises rather than
     pushing the menu button out of the bar. */
  .ln-bar.ln-site > .ln-bar-brand {
    min-width: 0;
    font-size: var(--ln-fs-callout);
  }
}

/* A figure worth a glance: label, value, an optional trend and note. Layout
   only; put it in a card, or several in `.ln-stat-grid`. */
.ln-stat {
  display: grid;
  gap: var(--ln-xs);
  align-content: start;
  min-width: 0;
}
.ln-stat > .ln-stat-label {
  font-size: var(--ln-fs-caption);
  font-weight: var(--ln-weight-strong);
  color: var(--ln-ink-quiet);
}
.ln-stat > .ln-stat-value {
  font-size: var(--ln-fs-display);
  font-weight: var(--ln-weight-heavy);
  line-height: 1.1;
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
}
.ln-stat.ln-quiet > .ln-stat-value {
  font-size: var(--ln-fs-title);
  font-weight: var(--ln-weight-strong);
}
/* Trend arrows point up and down in both directions: they mean more and
   less, not forward and back. */
.ln-stat-delta {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  justify-self: start;
  font-size: var(--ln-fs-caption);
  font-weight: var(--ln-weight-strong);
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
  color: var(--ln-ink-quiet);
}
.ln-stat-delta[data-trend='up'] {
  color: var(--ln-positive);
}
.ln-stat-delta[data-trend='down'] {
  color: var(--ln-critical);
}
.ln-stat-delta[data-trend='up']::before {
  content: '↑';
}
.ln-stat-delta[data-trend='down']::before {
  content: '↓';
}
.ln-stat-delta[data-trend='flat']::before {
  content: '–';
}
/* For a figure where less is better: the arrow stays, the verdict flips. */
.ln-stat-delta[data-good='down'][data-trend='down'] {
  color: var(--ln-positive);
}
.ln-stat-delta[data-good='down'][data-trend='up'] {
  color: var(--ln-critical);
}
.ln-stat > .ln-stat-note {
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
.ln-stat > .ln-stat-spark {
  display: block;
  width: 100%;
  height: 32px;
  margin-block-start: var(--ln-xs);
}
.ln-stat-grid {
  --ln-stat-gap: var(--ln-md);
  display: grid;
  gap: var(--ln-stat-gap);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 160px), 1fr));
}
/* Label / value pairs on one line: "Today · 7 days · 30 days". */
.ln-stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ln-md) var(--ln-xl);
  margin: 0;
}
.ln-stat-row > div {
  display: grid;
  gap: var(--ln-hair);
}
.ln-stat-row dt {
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
.ln-stat-row dd {
  margin: 0;
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
}

/* Labeled comparison bars, one per row. `data-ours` marks the row the page is
   about; the rest recede. Each row sets its own `--ln-meter` (0…1). */
.ln-meter-list {
  display: grid;
  gap: var(--ln-md);
  margin: 0;
  padding: 0;
  list-style: none;
}
.ln-meter-list > .ln-meter {
  --ln-meter-tint: color-mix(in srgb, var(--ln-ink) 34%, transparent);
}
.ln-meter-list > .ln-meter > .ln-meter-label {
  font-weight: 500;
}
.ln-meter-list > .ln-meter[data-ours] {
  --ln-meter-tint: var(--ln-accent);
}
.ln-meter-list > .ln-meter[data-ours] > .ln-meter-label,
.ln-meter-list > .ln-meter[data-ours] > .ln-meter-value {
  color: var(--ln-ink);
  font-weight: var(--ln-weight-heavy);
}
.ln-meter > .ln-meter-sub {
  grid-column: 1 / -1;
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
.ln-meter-caption {
  margin: var(--ln-sm) 0 0;
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}

/* A plan or price card. Put it on a surface: `<article class="ln-surface
   ln-plan">`. The action sits at the bottom so a row of plans aligns. */
.ln-plan {
  display: flex;
  flex-direction: column;
  gap: var(--ln-md);
  padding: var(--ln-xl);
  border-radius: var(--ln-r-lg);
}
.ln-plan > .ln-plan-head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--ln-sm);
}
.ln-plan .ln-plan-name {
  margin: 0;
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
}
.ln-plan > .ln-plan-price {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--ln-xs) var(--ln-sm);
  margin: 0;
}
.ln-plan-price > :first-child {
  font-size: var(--ln-fs-display);
  font-weight: var(--ln-weight-heavy);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
}
.ln-plan-price > .ln-plan-period {
  font-size: var(--ln-fs-callout);
  color: var(--ln-ink-quiet);
}
.ln-plan > .ln-plan-detail {
  margin: 0;
  font-size: var(--ln-fs-callout);
  color: var(--ln-ink-quiet);
}
.ln-plan > .ln-plan-limits {
  display: grid;
  gap: var(--ln-sm);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--ln-fs-callout);
}
.ln-plan-limits > li {
  display: flex;
  gap: var(--ln-sm);
}
.ln-plan-limits > li::before {
  content: '✓';
  flex: none;
  color: var(--ln-positive);
  font-weight: var(--ln-weight-heavy);
}
.ln-plan > :last-child:is(.ln-btn, a, button, form) {
  margin-block-start: auto;
}
/* Recommended is the offer, so it takes the accent edge. Current is a fact,
   not an offer: a positive hairline and no extra weight, so a row with both
   never shows two identical highlighted cards. */
.ln-plan[data-recommended] {
  border-color: color-mix(in srgb, var(--ln-accent) 55%, transparent);
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ln-accent) 55%, transparent),
    var(--ln-e-raised);
}
.ln-plan[data-current]:not([data-recommended]) {
  border-color: color-mix(in srgb, var(--ln-positive) 55%, transparent);
}
.ln-plan.ln-quiet {
  box-shadow: none;
}
.ln-plan-grid {
  display: grid;
  gap: var(--ln-lg);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr));
  align-items: stretch;
}

/* Onboarding or a flow's steps, each todo, current or done. The number is a
   counter, so it follows `data-ln-numerals="arab"`. */
.ln-steps {
  display: grid;
  gap: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: ln-step;
}
.ln-steps > li {
  position: relative;
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr);
  column-gap: var(--ln-md);
  padding-block-end: var(--ln-lg);
  counter-increment: ln-step;
}
.ln-steps > li:last-child {
  padding-block-end: 0;
}
.ln-steps > li::before {
  content: counter(ln-step);
  grid-row: 1 / span 2;
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border: 1.5px solid var(--ln-hairline-strong);
  border-radius: 50%;
  background: var(--ln-surface);
  color: var(--ln-ink-quiet);
  font-size: var(--ln-fs-caption);
  font-weight: var(--ln-weight-strong);
  font-variant-numeric: tabular-nums;
}
[data-ln-numerals='arab'] .ln-steps > li::before {
  content: counter(ln-step, arabic-indic);
}
/* The rail between two markers. */
.ln-steps > li:not(:last-child)::after {
  content: '';
  position: absolute;
  inset-block: 32px 4px;
  inset-inline-start: 13px;
  width: 2px;
  border-radius: 1px;
  background: var(--ln-hairline-strong);
}
.ln-steps > li > .ln-step-title {
  align-self: center;
  min-height: 28px;
  display: flex;
  align-items: center;
  font-weight: var(--ln-weight-strong);
  color: var(--ln-ink);
}
.ln-steps > li > .ln-step-detail {
  grid-column: 2;
  font-size: var(--ln-fs-callout);
  color: var(--ln-ink-quiet);
}
.ln-steps > li[data-state='current']::before {
  border-color: var(--ln-accent);
  background: var(--ln-accent);
  color: var(--ln-on-accent);
}
.ln-steps > li[data-state='done']::before {
  content: '✓';
  border-color: var(--ln-positive-fill);
  background: var(--ln-positive-fill);
  color: var(--ln-on-positive);
}
.ln-steps > li[data-state='done']:not(:last-child)::after {
  background: var(--ln-positive-fill);
}
/* Done is the check and a quieter title, never a strike: struck reads as
   cancelled, and the title is often still a link back to that step. */
.ln-steps > li[data-state='done'] > .ln-step-title {
  color: var(--ln-ink-quiet);
  font-weight: 500;
}
/* Inline: "1 Choose file › 2 Direction › 3 Pay" on one wrapping line. */
.ln-steps.ln-inline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ln-sm) var(--ln-md);
}
.ln-steps.ln-inline > li {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-sm);
  padding: 0;
}
.ln-steps.ln-inline > li::before {
  width: 22px;
  height: 22px;
  font-size: var(--ln-fs-micro);
}
.ln-steps.ln-inline > li:not(:last-child)::after {
  content: '›';
  position: static;
  width: auto;
  background: none;
  color: var(--ln-ink-tertiary);
}
.ln-steps.ln-inline > li > .ln-step-title {
  min-height: 0;
  font-size: var(--ln-fs-callout);
}
.ln-steps.ln-inline > li > .ln-step-detail {
  display: none;
}

/* A privacy or analytics choice: title, body, the current state in words,
   and actions. In place by default; `ln-docked` pins it to the bottom edge
   and `ln-floating` to the bottom inline-end corner. */
.ln-consent {
  display: grid;
  gap: var(--ln-sm);
  padding: var(--ln-lg);
}
.ln-consent > .ln-consent-title {
  margin: 0;
  font-size: var(--ln-fs-headline);
  font-weight: var(--ln-weight-strong);
}
.ln-consent > .ln-consent-body {
  margin: 0;
  font-size: var(--ln-fs-callout);
  color: var(--ln-ink-quiet);
}
.ln-consent-state {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-sm);
  margin: 0;
  font-size: var(--ln-fs-callout);
  font-weight: var(--ln-weight-strong);
}
.ln-consent-state::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ln-ink-tertiary);
}
.ln-consent-state[data-state='on']::before {
  background: var(--ln-positive);
}
.ln-consent > .ln-consent-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ln-sm);
  margin-block-start: var(--ln-xs);
}
.ln-consent > .ln-consent-close {
  position: absolute;
  inset-block-start: var(--ln-xs);
  inset-inline-end: var(--ln-xs);
  --ln-icon-size: 44px;
  --ln-icon-glyph: 13px;
}
.ln-consent:not([data-dismissible]) > .ln-consent-close {
  display: none;
}
.ln-consent[data-dismissible] {
  padding-inline-end: 52px;
}
.ln-consent.ln-docked,
.ln-consent.ln-floating {
  position: fixed;
  z-index: 80;
  box-shadow: var(--ln-e-floating);
}
.ln-consent.ln-docked {
  inset-inline: 0;
  bottom: 0;
  border-radius: var(--ln-r-lg) var(--ln-r-lg) 0 0;
  border-block-end: 0;
}
.ln-consent.ln-floating {
  inset-inline-end: var(--ln-lg);
  bottom: var(--ln-lg);
  width: min(380px, calc(100vw - var(--ln-lg) * 2));
}
.ln-consent[hidden] {
  display: none;
}

/* Code with a copy button. The code stays LTR; the header follows the page. */
.ln-code {
  display: flex;
  flex-direction: column;
  margin: 0;
  min-width: 0;
  border: 1px solid var(--ln-hairline-faint);
  border-radius: var(--ln-r-sm);
  background: var(--ln-well);
  box-shadow: var(--ln-inner);
  overflow: hidden;
}
.ln-code > .ln-code-head {
  display: flex;
  align-items: center;
  gap: var(--ln-sm);
  min-height: 44px;
  padding-inline: var(--ln-md) var(--ln-xs);
  border-block-end: 1px solid var(--ln-hairline-faint);
}
.ln-code-head > .ln-code-lang {
  flex: 1;
  font-size: var(--ln-fs-micro);
  font-weight: var(--ln-weight-strong);
  letter-spacing: var(--ln-label-tracking);
  text-transform: var(--ln-label-case);
  color: var(--ln-ink-quiet);
}
.ln-code-head > .ln-segmented {
  margin-inline-end: auto;
}
.ln-code-head > .ln-segmented > button {
  min-height: 32px;
  padding: 4px 12px;
  font-size: var(--ln-fs-caption);
}
.ln-code-head > .ln-code-copy {
  min-height: 36px;
}
/* Panels switched by `Lantern.tabs` from a `.ln-segmented[role=tablist]` in the
   head. A panel that isn't a `pre` is rendered markup, padded like the code. */
.ln-code > :is(pre, [role='tabpanel']) {
  flex: 1 1 auto;
  min-height: 0;
}
.ln-code > [role='tabpanel']:not(pre) {
  padding: var(--ln-md);
  overflow: auto;
}
/* The UA gives `code` its own `monospace`, which is Courier in Chrome. */
.ln-code pre > code {
  font: inherit;
}
.ln-code > pre {
  margin: 0;
  padding: var(--ln-md);
  overflow-x: auto;
  direction: ltr;
  text-align: left;
  font-family: var(--ln-font-mono);
  font-size: var(--ln-fs-caption);
  line-height: 1.55;
  tab-size: 2;
}
.ln-code > pre[hidden] {
  display: none;
}

/* ========================================================================== *
 * Extensions — progress, tables, disclosure
 * ========================================================================== */

/* A label over a bar: text at the start, the reading at the end. */
.ln-progress-label {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--ln-md);
  margin-block-end: var(--ln-xs);
  font-size: var(--ln-fs-callout);
}
.ln-progress-label > :last-child:not(:first-child) {
  color: var(--ln-ink-quiet);
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
}
/* Work of unknown length: a sheen that travels along the track. Under reduced
   motion it holds still as a faint full bar. */
.ln-progress.ln-indeterminate > .ln-progress-fill {
  width: 38%;
  min-width: 0;
  animation: ln-indeterminate 1.3s var(--ln-ease) infinite;
}
.ln-progress.ln-indeterminate:dir(rtl) > .ln-progress-fill {
  animation-name: ln-indeterminate-rtl;
}
@keyframes ln-indeterminate {
  from {
    transform: translateX(-105%);
  }
  to {
    transform: translateX(270%);
  }
}
@keyframes ln-indeterminate-rtl {
  from {
    transform: translateX(105%);
  }
  to {
    transform: translateX(-270%);
  }
}
/* Partial data ("recorded since…"): hatched rather than solid. */
.ln-progress.ln-partial > .ln-progress-fill,
.ln-legend-swatch.ln-partial {
  background-color: transparent;
  background-image: repeating-linear-gradient(
    135deg,
    var(--ln-progress-tint, var(--ln-accent)) 0 3px,
    color-mix(in srgb, var(--ln-progress-tint, var(--ln-accent)) 35%, transparent) 3px 6px
  );
}
.ln-legend-swatch {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  background: var(--ln-progress-tint, var(--ln-accent));
  vertical-align: -1px;
}
/* Stages (upload → processing): `--ln-steps` equal stages, divided by a notch
   in the track. */
.ln-progress.ln-staged {
  --ln-steps: 2;
  height: 8px;
}
.ln-progress.ln-staged::after {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(
    to right,
    transparent 0 calc(100% / var(--ln-steps) - 1px),
    var(--ln-surface) calc(100% / var(--ln-steps) - 1px) calc(100% / var(--ln-steps) + 1px)
  );
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .ln-progress.ln-indeterminate > .ln-progress-fill {
    width: 100%;
    opacity: 0.35;
    animation: none;
  }
}

/* Tables: numeric columns, sticky header, density, sorting, a pager, and
   rows that stack into cards on a phone. */
.ln-table :is(th, td)[data-num] {
  text-align: end;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ln-table.ln-sticky-head thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  background: var(--ln-surface);
  box-shadow: inset 0 -1px 0 var(--ln-hairline);
}
.ln-table.ln-dense :is(th, td) {
  padding: var(--ln-xs) var(--ln-sm);
}
.ln-table th[aria-sort] > button {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-xs);
  min-height: 32px;
  margin: -6px -4px;
  padding: 6px 4px;
  border: 0;
  border-radius: var(--ln-r-xs);
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  cursor: pointer;
}
.ln-table th[aria-sort] > button:hover {
  color: var(--ln-ink);
}
.ln-table th[aria-sort] > button::after {
  content: '↕';
  color: var(--ln-ink-tertiary);
  font-size: 1.1em;
}
.ln-table th[aria-sort='ascending'] > button::after {
  content: '↑';
  color: var(--ln-accent);
}
.ln-table th[aria-sort='descending'] > button::after {
  content: '↓';
  color: var(--ln-accent);
}
.ln-table-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--ln-sm) var(--ln-md);
  padding: var(--ln-sm) var(--ln-md);
  border-block-start: 1px solid var(--ln-hairline-faint);
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
.ln-pager {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-sm);
}
.ln-pager > .ln-pager-range {
  font-variant-numeric: tabular-nums;
  unicode-bidi: isolate;
}
.ln-pager > button {
  --ln-icon-size: 40px;
}
@media (max-width: 640px) {
  .ln-table.ln-stack-sm,
  .ln-table.ln-stack-sm tbody,
  .ln-table.ln-stack-sm tr,
  .ln-table.ln-stack-sm td {
    display: block;
  }
  .ln-table.ln-stack-sm thead {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
  }
  .ln-table.ln-stack-sm tr {
    padding-block: var(--ln-sm);
    border-block-end: 1px solid var(--ln-hairline);
  }
  .ln-table.ln-stack-sm tbody tr:last-child {
    border-block-end: 0;
  }
  .ln-table.ln-stack-sm td {
    display: grid;
    grid-template-columns: minmax(7em, 38%) minmax(0, 1fr);
    gap: var(--ln-md);
    padding: var(--ln-xs) var(--ln-md);
    border: 0;
    text-align: start;
  }
  .ln-table.ln-stack-sm td::before {
    content: attr(data-label);
    color: var(--ln-ink-quiet);
    font-size: var(--ln-fs-caption);
    font-weight: var(--ln-weight-strong);
  }
  .ln-table.ln-stack-sm td[data-num] {
    white-space: normal;
  }
}

/* Disclosure variants. `ln-card` gives it its own surface; `ln-bordered` is a
   hairline-ruled list for FAQs. Summaries keep a 44px target. */
details.ln-details > summary {
  min-height: 44px;
}
details.ln-details.ln-card {
  padding-block: var(--ln-xs);
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-r-md);
  background: var(--ln-surface);
  box-shadow: var(--ln-e-resting);
}
details.ln-details.ln-bordered {
  border-block: 1px solid var(--ln-hairline);
}
details.ln-details.ln-bordered + details.ln-details.ln-bordered {
  border-block-start: 0;
}
/* An inline disclosure: a quiet link-like summary with a chevron after it that
   turns down on open. */
details.ln-disclosure > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--ln-xs);
  min-height: 44px;
  color: var(--ln-accent);
  font-size: var(--ln-fs-callout);
  font-weight: 500;
  list-style: none;
  cursor: pointer;
}
details.ln-disclosure > summary::-webkit-details-marker {
  display: none;
}

/* ========================================================================== *
 * Controls and chrome — tabs, menus, checks, meta, banners
 * ========================================================================== */

/* A segmented control can be a tab list: the selected tab takes the pressed
   look. `.ln-tabs` is the underlined form for page-level tab sets.
   `Lantern.tabs` wires roving focus and arrow keys, mirrored in RTL. */
.ln-tabs {
  display: flex;
  gap: var(--ln-lg);
  overflow-x: auto;
  border-block-end: 1px solid var(--ln-hairline);
  scrollbar-width: none;
}
.ln-tabs > [role='tab'] {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  margin-block-end: -1px;
  padding: 0 var(--ln-xs);
  border: 0;
  border-block-end: 2px solid transparent;
  background: none;
  color: var(--ln-ink-quiet);
  font: inherit;
  font-size: var(--ln-fs-callout);
  font-weight: 500;
  white-space: nowrap;
  cursor: pointer;
}
.ln-tabs > [role='tab']:hover {
  color: var(--ln-ink);
}
.ln-tabs > [role='tab'][aria-selected='true'] {
  color: var(--ln-accent);
  border-block-end-color: currentColor;
  font-weight: var(--ln-weight-strong);
}
[role='tabpanel'][hidden] {
  display: none;
}

/* A menu, usually a `[popover]` anchored by `Lantern.menu`. A bottom sheet on
   a phone. */
.ln-menu {
  min-width: 200px;
  max-width: min(320px, calc(100vw - var(--ln-lg) * 2));
  margin: 0;
  padding: var(--ln-xs);
  border: 1px solid var(--ln-hairline);
  border-radius: var(--ln-r-sm);
  background-color: var(--ln-surface);
  box-shadow: var(--ln-e-floating);
  color: var(--ln-ink);
}
.ln-menu:not([popover])[hidden] {
  display: none;
}
.ln-menu:not([popover]) {
  position: fixed;
  z-index: 60;
}
.ln-menu > .ln-separator {
  margin: var(--ln-xs) 0;
}
.ln-menu-item {
  display: flex;
  align-items: center;
  gap: var(--ln-sm);
  width: 100%;
  min-height: 40px;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--ln-r-xs);
  background: none;
  color: inherit;
  font: inherit;
  font-size: var(--ln-fs-callout);
  text-align: start;
  text-decoration: none;
  cursor: pointer;
}
.ln-menu-item:hover,
.ln-menu-item:focus-visible {
  background: var(--ln-hover-wash);
}
/* Keyboard focus is a ring, not only the hover wash: arrowing through a menu
   under a resting pointer would otherwise show two identical washes. Inset, so
   the menu's padding never clips it. */
.ln-menu-item:focus-visible {
  outline: 2px solid var(--ln-focus);
  outline-offset: -2px;
}
.ln-menu-item.ln-destructive {
  color: var(--ln-critical);
}
@media (max-width: 600px) {
  .ln-menu {
    position: fixed;
    inset: auto 0 0 !important;
    width: 100%;
    max-width: none;
    padding: var(--ln-sm) var(--ln-sm) calc(var(--ln-sm) + env(safe-area-inset-bottom));
    border-radius: var(--ln-r-lg) var(--ln-r-lg) 0 0;
  }
  .ln-menu-item {
    min-height: 48px;
    font-size: var(--ln-fs-body);
  }
}

/* A dialog that is centred on a wide screen and a bottom sheet on a phone —
   what `Lantern.confirm` builds. The primary action sits at the inline end. */
@media (max-width: 600px) {
  dialog.ln-dialog.ln-dock {
    width: 100vw;
    max-width: none;
    max-height: 88vh;
    margin: auto 0 0;
    border-radius: var(--ln-r-lg) var(--ln-r-lg) 0 0;
    padding-block-end: env(safe-area-inset-bottom);
  }
  dialog.ln-dialog.ln-dock[open] {
    animation-name: ln-sheet-up;
  }
  dialog.ln-dialog.ln-dock .ln-dialog-foot > .ln-btn {
    flex: 1;
  }
}
@keyframes ln-sheet-up {
  from {
    transform: translateY(24px);
    opacity: 0;
  }
}

/* A checkbox or radio with its label, and an optional hint under it. The box
   is drawn at 20px; the label row keeps a 44px target. */
.ln-check,
.ln-radio {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  align-items: start;
  column-gap: var(--ln-md);
  min-height: 44px;
  padding-block: 10px;
  cursor: pointer;
}
.ln-check > input,
.ln-radio > input {
  width: 20px;
  height: 20px;
  margin: 1px 0 0;
  accent-color: var(--ln-accent);
  cursor: pointer;
}
.ln-check > .ln-check-label,
.ln-radio > .ln-check-label {
  display: grid;
  gap: var(--ln-hair);
}
.ln-check-hint {
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}
.ln-check:has(> input:disabled),
.ln-radio:has(> input:disabled) {
  opacity: 0.55;
  cursor: default;
}

/* A metadata line: parts divided by a hairline, never by "·", which next to
   Arabic-Indic digits reads as a zero. */
.ln-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--ln-hair) 1.2em;
  margin: 0;
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
  /* The separator hangs in the gap before its item, so on a wrapped line's
     first item it falls outside the box and is clipped. The clip margin
     leaves room for a focus ring on a link at the edge. */
  overflow-x: clip;
  overflow-clip-margin: 4px;
}
.ln-meta > * {
  position: relative;
  unicode-bidi: isolate;
}
.ln-meta > * + *::before {
  content: '';
  position: absolute;
  inset-inline-start: calc(-0.6em - 0.5px);
  top: 50%;
  width: 1px;
  height: 0.9em;
  translate: 0 -50%;
  background: currentColor;
  opacity: 0.45;
}

/* States gain an action row, a dashed card form, and a loading form. */
.ln-state > .ln-state-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--ln-sm);
  margin-block-start: var(--ln-xs);
}
.ln-state.ln-state-card {
  border: 1.5px dashed var(--ln-hairline-strong);
  border-radius: var(--ln-r-md);
  background: var(--ln-well);
}
.ln-state.ln-loading > .ln-state-glyph {
  font-size: 0;
}
:lang(ar) .ln-state > .ln-state-detail {
  max-width: 42ch;
}

/* A sticky banner at the foot of the page, for a failure that must stay in
   view. Dismiss with a `.ln-icon-btn` inside it. */
.ln-banner.ln-page-banner {
  position: sticky;
  bottom: var(--ln-md);
  z-index: 40;
  margin-inline: auto;
  width: min(100%, 640px);
  padding-inline-end: var(--ln-xs);
  border-radius: var(--ln-r-md);
  box-shadow: var(--ln-e-floating);
  background-color: var(--ln-surface);
  background-image: linear-gradient(
    color-mix(in srgb, var(--ln-banner-color, var(--ln-caution)) 12%, transparent),
    color-mix(in srgb, var(--ln-banner-color, var(--ln-caution)) 12%, transparent)
  );
}
.ln-banner > .ln-icon-btn {
  --ln-icon-size: 40px;
  --ln-icon-glyph: 13px;
  flex: none;
  color: inherit;
}

/* Skeleton lines for text (`--ln-lines`) and a player bar. RTL shimmers from
   the right. */
.ln-skeleton:dir(rtl) {
  animation-direction: reverse;
}
/* Use with `.ln-skeleton`: the shimmer shows through a mask of `--ln-lines`
   text lines, the last one shorter, on the reading side. */
.ln-skeleton.ln-skeleton-text {
  --ln-lines: 3;
  --ln-skeleton-line: 14px;
  --ln-skeleton-gap: 12px;
  --ln-skeleton-last: 62%;
  height: calc(var(--ln-lines) * (var(--ln-skeleton-line) + var(--ln-skeleton-gap)) - var(--ln-skeleton-gap));
  border-radius: 0;
  --ln-skeleton-mask:
    repeating-linear-gradient(
      #000 0 var(--ln-skeleton-line),
      transparent var(--ln-skeleton-line) calc(var(--ln-skeleton-line) + var(--ln-skeleton-gap))
    ),
    linear-gradient(#000, #000);
  mask-image: var(--ln-skeleton-mask);
  -webkit-mask-image: var(--ln-skeleton-mask);
  mask-size:
    100% calc(100% - var(--ln-skeleton-line)),
    var(--ln-skeleton-last) var(--ln-skeleton-line);
  -webkit-mask-size:
    100% calc(100% - var(--ln-skeleton-line)),
    var(--ln-skeleton-last) var(--ln-skeleton-line);
  mask-position:
    0 0,
    left bottom;
  -webkit-mask-position:
    0 0,
    left bottom;
  mask-repeat: no-repeat;
  -webkit-mask-repeat: no-repeat;
}
/* For pages whose CSP refuses style attributes. */
.ln-skeleton-text[data-lines='1'] {
  --ln-lines: 1;
}
.ln-skeleton-text[data-lines='2'] {
  --ln-lines: 2;
}
.ln-skeleton-text[data-lines='4'] {
  --ln-lines: 4;
}
.ln-skeleton-text[data-lines='5'] {
  --ln-lines: 5;
}
.ln-skeleton-text[data-lines='6'] {
  --ln-lines: 6;
}
.ln-skeleton.ln-skeleton-text:dir(rtl) {
  mask-position:
    0 0,
    right bottom;
  -webkit-mask-position:
    0 0,
    right bottom;
}
/* The height of a native audio player, so the page does not move when it lands. */
.ln-skeleton.ln-skeleton-player {
  height: 54px;
  border-radius: var(--ln-r-pill);
}

/* The Auto / Light / Dark choice, built by `Lantern.themeSwitch`. */
.ln-theme-switch > button {
  min-width: 44px;
  padding-inline: 10px;
}
.ln-theme-switch svg {
  width: 18px;
  height: 18px;
}

/* An echo of a native date field in the page's own locale: a `<input
   type=date>` shows mm/dd/yyyy on an Arabic page. `Lantern.echoDates`. */
.ln-field-echo {
  display: block;
  min-height: 1.35em;
  margin-top: var(--ln-xs);
  font-size: var(--ln-fs-caption);
  color: var(--ln-ink-quiet);
}

/* ========================================================================== *
 * Touch targets and forced colours
 * ========================================================================== */

/* Under a finger, every compact control reaches 44px without being drawn any
   larger: an invisible hit area centred on it, as `.ln-target` does for a
   link. Skips the elements whose `::after` already has a job. */
@media (pointer: coarse) {
  :is(.ln-btn, .ln-icon-btn, button.ln-pill, a.ln-pill, .ln-segmented > label, .ln-segmented > button):not(.ln-bloom, [data-ln-tip])::after {
    content: '';
    position: absolute;
    inset-block: min(0px, calc((100% - 44px) / 2));
    inset-inline: min(0px, calc((100% - 44px) / 2));
  }
  button.ln-pill,
  a.ln-pill {
    position: relative;
  }
}

/* Windows High Contrast and other forced palettes drop backgrounds and box
   shadows, which is where several controls keep their state. Restate those
   states in system colours. */
@media (forced-colors: active) {
  .ln-switch:has(> input:checked) {
    background: Highlight;
    forced-color-adjust: none;
  }
  .ln-switch > .ln-switch-knob {
    background: CanvasText;
    forced-color-adjust: none;
  }
  .ln-switch:has(> input:checked) > .ln-switch-knob {
    background: HighlightText;
  }
  .ln-segmented > label:has(input:checked),
  .ln-segmented > button[aria-pressed='true'],
  .ln-segmented > [role='tab'][aria-selected='true'],
  button.ln-pill[aria-pressed='true'],
  .ln-pill.ln-selected {
    border-color: Highlight;
    outline: 2px solid Highlight;
    outline-offset: -2px;
  }
  .ln-bar-nav > a[aria-current],
  .ln-sheet-nav > a[aria-current],
  .ln-sidebar-nav > a[aria-current='page'],
  .ln-row.ln-selected {
    outline: 2px solid Highlight;
    outline-offset: -2px;
  }
  .ln-progress-fill,
  .ln-meter-fill,
  .ln-live-dot,
  .ln-level::before,
  .ln-file-status::before,
  .ln-consent-state::before {
    background: Highlight;
    forced-color-adjust: none;
  }
  .ln-ring {
    background: conic-gradient(Highlight calc(var(--ln-progress) * 360deg), Canvas 0);
    border: 1px solid CanvasText;
    forced-color-adjust: none;
  }
  .ln-ring::before {
    background: Canvas;
  }
  .ln-spinner {
    border-top-color: Highlight;
  }
  /* A swatch is the colour itself; a forced palette would erase its content. */
  .ln-swatch {
    forced-color-adjust: none;
  }
  /* A quiet button has no edge, so in a forced palette it would be bare text. */
  .ln-btn.ln-quiet-btn,
  .ln-btn.ln-quiet-destructive,
  .ln-icon-btn.ln-bare {
    border-color: ButtonText;
  }
}

/* ========================================================================== *
 * Arabic interface scale — automatic under `lang="ar"`, or `.ln-ar-ui`
 * ========================================================================== */

/* Latin micro sizes are too small for Arabic UI text (11px micro, 13px
   caption), Arabic needs more leading, and a label must never be smaller than
   the hint under it. */
:root:lang(ar),
.ln-ar-ui {
  --ln-fs-micro: 0.8125rem;
  --ln-fs-caption: 0.875rem;
  --ln-fs-callout: 1rem;
}
/* One class of weight, so it lifts the micro label but never shrinks a label
   a layout has already set larger (`.ln-field > label`). */
:where(:lang(ar), .ln-ar-ui) .ln-field-label {
  font-size: 0.875rem;
}
:lang(ar) :is(.ln-body, .ln-field-hint, .ln-caption),
.ln-ar-ui :is(.ln-body, .ln-field-hint, .ln-caption) {
  line-height: 1.7;
}
/* Tracking breaks Arabic joins, whatever the size. */
:lang(ar) :is(.ln-micro, .ln-section-header, .ln-field-label, .ln-pill, .ln-code-lang, .ln-choice-group > legend, .ln-table th) {
  letter-spacing: 0;
  text-transform: none;
}

/* ========================================================================== *
 * Flat style — `data-ln-style="flat"` on the root or a subtree
 * ========================================================================== */

/* The same tokens without the material: no grain, sheen, lip or inner shadow,
   and only a contact shadow on floating things. For a product that wants the
   language's colour and type in a plainer finish. `--ln-radius-control` sets
   the corner of buttons and fields in either style. */
[data-ln-style='flat'] {
  --ln-grain: none;
  --ln-sheen: none;
  --ln-sheen-quiet: none;
  --ln-sheen-lit: none;
  --ln-lip: transparent;
  --ln-lip-lit: transparent;
  --ln-inner: none;
  --ln-e-resting: none;
  --ln-e-raised: 0 1px 2px light-dark(rgb(0 0 0 / 0.06), rgb(0 0 0 / 0.3));
  --ln-btn-gloss: none;
  --ln-btn-lip: transparent;
  --ln-btn-shadow: none;
  --ln-radius-control: var(--ln-r-xs);
}
[data-ln-style='flat'] .ln-progress > .ln-progress-fill {
  background-image: none;
}

/* Between the two: the finish at a little over half strength and no grain.
   Buttons keep their lip and gloss, cards their contact shadow, floating layers
   their full shadow. Controls take the flat style's tighter corner. Retune
   with `--ln-depth` (0 to 1) on the same element. */
[data-ln-style='soft'] {
  --ln-depth: 0.55;
  --ln-grain: none;
  --ln-radius-control: var(--ln-r-xs);
}

/* ========================================================================== *
 * Instrument theme — `data-ln-theme="instrument"` on the root or a subtree
 * ========================================================================== */

/* Hallmark · macrostructure: none (design-system theme; each site keeps its own) · scope: Lantern token theme
 * theme: custom · vibe: "precise technical instrument, follows Lantern" · paper: oklch(96.6% 0.005 255) · accent: oklch(45% 0.140 258)
 * display: IBM Plex Sans / IBM Plex Sans Arabic 600–700 · body: the same family 400 · mono: IBM Plex Mono · axes: light / geometric-sans / cool
 * studied: no · context: explicit · v1.1.0
 */

/* Cool neutral paper, one ink-blue accent and crisp opaque rules, set in IBM
   Plex. Tokens only: every component, the flat style, the Arabic scale and RTL
   work unchanged. The fonts ship beside this file in `fonts/` and only download
   when a page renders with the theme on. Plex Sans and Plex Sans Arabic are one
   CSS family; `unicode-range` picks the file per character, so a mixed line
   never changes voice.
   To adopt it: serve `fonts/` beside wherever this file is served (the URLs are
   relative), then set the attribute. `--ln-control-edge` and
   `--ln-field-border` carry the 3:1 edge of fields, switches and sliders.
   Charts use `--ln-series-1` … `-6` in order, never cycled. The gallery's
   Palette switch, or `?palette=instrument`, shows every component under it. */
/* The variable Latin file is declared once per Arabic weight, not as one
   100–700 range: WebKit and Blink pick faces by weight before script, so a
   range face beside an exact Arabic 400 lost Latin text to the fallback. The
   four rules share one URL and download once. */
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-latin.woff2') format('woff2');
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-latin.woff2') format('woff2');
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-latin.woff2') format('woff2');
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-latin.woff2') format('woff2');
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-latin-italic.woff2') format('woff2');
  font-style: italic;
  font-weight: 100 700;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-arabic-400.woff2') format('woff2');
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-arabic-500.woff2') format('woff2');
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-arabic-600.woff2') format('woff2');
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'Lantern Instrument Sans';
  src: url('fonts/plex-sans-arabic-700.woff2') format('woff2');
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'Lantern Instrument Mono';
  src: url('fonts/plex-mono-latin-400.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Lantern Instrument Mono';
  src: url('fonts/plex-mono-latin-600.woff2') format('woff2');
  font-weight: 600;
  font-display: swap;
}

[data-ln-theme='instrument'] {
  /* Accent: ink-blue. White on it is 7.4:1; as a ring it clears 3:1 on every surface. */
  --ln-accent-light: oklch(45% 0.14 258);
  --ln-accent-dark: oklch(75% 0.11 250);
  --ln-accent: light-dark(var(--ln-accent-light), var(--ln-accent-dark));
  --ln-on-accent: light-dark(oklch(98.6% 0.005 255), oklch(18% 0.03 258));
  --ln-focus: light-dark(oklch(50% 0.18 258), oklch(78% 0.105 250));
  --ln-ember: light-dark(oklch(52% 0.12 50), oklch(76% 0.11 58));
  --ln-on-ember: light-dark(oklch(98.6% 0.005 255), oklch(20% 0.03 60));

  /* Paper. Chroma never drops to zero; hue 255 keeps it cool without reading blue. */
  --ln-canvas-top: light-dark(oklch(97.6% 0.005 255), oklch(19.5% 0.01 258));
  --ln-canvas-bottom: light-dark(oklch(95.4% 0.005 255), oklch(14.8% 0.009 258));
  --ln-canvas: light-dark(oklch(96.6% 0.005 255), oklch(17% 0.01 258));
  --ln-surface: light-dark(oklch(98.9% 0.005 255), oklch(21.5% 0.011 258));
  --ln-surface-quiet: light-dark(oklch(93.2% 0.006 255), oklch(26% 0.012 258));
  --ln-well: light-dark(oklch(95.2% 0.005 255), oklch(15.8% 0.009 258));

  /* Ink. Opaque, and every tier, tertiary included, clears 4.5:1 on every paper level. */
  --ln-ink: light-dark(oklch(21% 0.02 260), oklch(95.5% 0.005 255));
  --ln-ink-secondary: light-dark(oklch(42% 0.02 258), oklch(78% 0.012 255));
  --ln-ink-quiet: light-dark(oklch(46% 0.018 258), oklch(74% 0.012 255));
  --ln-ink-tertiary: light-dark(oklch(51% 0.016 258), oklch(66% 0.012 255));
  --ln-ink-placeholder: var(--ln-ink-tertiary);

  --ln-positive: light-dark(oklch(46.5% 0.095 162), oklch(76% 0.11 162));
  --ln-caution: light-dark(oklch(50% 0.1 75), oklch(80% 0.11 80));
  --ln-critical: light-dark(oklch(50% 0.15 27), oklch(74% 0.12 25));
  --ln-positive-fill: light-dark(oklch(48% 0.095 162), oklch(44% 0.085 162));
  --ln-caution-fill: light-dark(oklch(48% 0.095 72), oklch(45% 0.09 72));
  --ln-critical-fill: light-dark(oklch(50% 0.15 27), oklch(46% 0.14 27));
  --ln-on-positive: oklch(98.6% 0.005 255);
  --ln-on-caution: oklch(98.6% 0.005 255);
  --ln-on-critical: oklch(98.6% 0.005 255);
  --ln-live: light-dark(oklch(54% 0.19 28), oklch(72% 0.17 27));
  --ln-highlight: light-dark(oklch(92% 0.075 95), oklch(40% 0.07 95));

  /* Rules. Opaque hairlines, and a 3:1 edge for controls with no text of their own. */
  --ln-hairline: light-dark(oklch(88% 0.007 255), oklch(31% 0.012 258));
  --ln-hairline-faint: light-dark(oklch(91.5% 0.006 255), oklch(27% 0.011 258));
  --ln-hairline-strong: light-dark(oklch(83% 0.009 255), oklch(37% 0.012 258));
  --ln-control-edge: light-dark(oklch(60% 0.014 256), oklch(55% 0.014 256));
  --ln-field-border: var(--ln-control-edge);
  --ln-field-focus: var(--ln-focus);
  --ln-scrim: light-dark(oklch(21% 0.02 260 / 0.3), oklch(8% 0.01 258 / 0.62));

  /* Charts: validated for colour-vision separation as adjacent pairs, in this order. */
  --ln-series-1: light-dark(oklch(52% 0.15 258), oklch(66% 0.13 255));
  --ln-series-2: light-dark(oklch(64% 0.15 48), oklch(66% 0.14 48));
  --ln-series-3: light-dark(oklch(58.5% 0.103 180), oklch(62% 0.105 182));
  --ln-series-4: light-dark(oklch(66% 0.13 82), oklch(64% 0.12 85));
  --ln-series-5: light-dark(oklch(56% 0.17 350), oklch(64% 0.15 355));
  --ln-series-6: light-dark(oklch(46% 0.15 295), oklch(54% 0.15 295));
  --ln-chart-grid: light-dark(oklch(90% 0.006 255), oklch(29% 0.011 258));
  --ln-chart-axis: var(--ln-control-edge);
  --ln-on-media-accent: oklch(75% 0.11 250);

  /* Everything :root derives from the tokens above, restated so a themed
     subtree derives from its own values rather than inheriting the root's. */
  --ln-accent-wash: light-dark(
    color-mix(in srgb, var(--ln-accent) 10%, transparent),
    color-mix(in srgb, var(--ln-accent) 16%, transparent)
  );
  --ln-hover-wash: light-dark(
    color-mix(in srgb, var(--ln-accent) 7%, transparent),
    color-mix(in srgb, var(--ln-accent) 12%, transparent)
  );
  --ln-current-wash: light-dark(
    color-mix(in srgb, var(--ln-accent) 16%, transparent),
    color-mix(in srgb, var(--ln-accent) 26%, transparent)
  );
  --ln-answer-wash: var(--ln-accent-wash);
  --ln-selection: light-dark(
    color-mix(in srgb, var(--ln-accent) 24%, transparent),
    color-mix(in srgb, var(--ln-accent) 36%, transparent)
  );
  --ln-grade-again: var(--ln-critical);
  --ln-grade-hard: var(--ln-caution);
  --ln-grade-good: var(--ln-positive);
  --ln-grade-easy: var(--ln-accent);
  --ln-glass: color-mix(in srgb, var(--ln-canvas) 82%, transparent);

  /* A step tighter than stock. Nothing is sharp. */
  --ln-r-xs: 6px;
  --ln-r-sm: 9px;
  --ln-r-md: 12px;
  --ln-r-lg: 16px;
  --ln-r-xl: 20px;

  /* Type. No serif in this theme: `.ln-meaning` sets in the sans italic. */
  --ln-font: 'Lantern Instrument Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --ln-font-ar: 'Lantern Instrument Sans', -apple-system, 'SF Arabic', 'Geeza Pro', 'Noto Naskh Arabic', 'Segoe UI', Tahoma, sans-serif;
  --ln-font-serif: var(--ln-font);
  /* Plex Mono has no Arabic-Indic digits; the theme's sans draws them (and any
     Arabic in code) instead of an unrelated system face. */
  --ln-font-mono: 'Lantern Instrument Mono', 'Lantern Instrument Sans', ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  /* Plex Arabic's ascenders meet the line above at Lantern's 1.22. */
  --ln-lh-ar: 1.4;
  /* So a themed subtree sets in the theme's face, not the one it inherits. */
  font-family: var(--ln-font);
}
/* Code, keys and samples set in Plex Mono, not the UA's monospace. Zero
   specificity, so any site rule wins; the size makes up for the UA's smaller
   monospace default, which stops applying once the family is named. */
[data-ln-theme='instrument'] :where(code, kbd, samp) {
  font-family: var(--ln-font-mono);
  font-size: 0.9em;
}

/* ========================================================================== *
 * After Hours theme — `data-ln-theme="after-hours"` on the root or a subtree
 * ========================================================================== */

/* A dark desktop late at night, where the product is the only lit thing. A
   near-black neutral ground, off-white ink and no hue: the accent is the ink,
   so the brightest object on screen is always the words or the action, and
   colour comes only from a product's own imagery. Dark only, flat, with one
   emphasis weight (560) in Hanken Grotesk and IBM Plex Sans Arabic as one
   family. Tokens only; to adopt it, serve `fonts/` beside this file and set the
   attribute. `data-theme="light"` has no effect under it.
   `--ln-ink-tertiary` (46%) passes contrast only at 28px and above; small text
   takes secondary or quiet. */
/* Each Arabic weight owns a band of the weight axis, and the variable Latin
   file is declared once per band with the same range, so 560 renders Latin at
   560 and Arabic from the 600 file. One URL per script, downloaded once. */
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/hanken-grotesk-latin.woff2') format('woff2');
  font-weight: 100 449;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/hanken-grotesk-latin.woff2') format('woff2');
  font-weight: 450 549;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/hanken-grotesk-latin.woff2') format('woff2');
  font-weight: 550 649;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/hanken-grotesk-latin.woff2') format('woff2');
  font-weight: 650 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/hanken-grotesk-latin-ext.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/hanken-grotesk-latin-italic.woff2') format('woff2');
  font-style: italic;
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/plex-sans-arabic-400.woff2') format('woff2');
  font-weight: 100 449;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/plex-sans-arabic-500.woff2') format('woff2');
  font-weight: 450 549;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/plex-sans-arabic-600.woff2') format('woff2');
  font-weight: 550 649;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}
@font-face {
  font-family: 'Lantern After Hours Sans';
  src: url('fonts/plex-sans-arabic-700.woff2') format('woff2');
  font-weight: 650 900;
  font-display: swap;
  unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+0890-0891, U+0897-08E1, U+08E3-08FF, U+200C-200E, U+2010-2011, U+204F, U+2E41, U+FB50-FDFF, U+FE70-FE74, U+FE76-FEFC;
}

[data-ln-theme='after-hours'],
[data-ln-theme='after-hours'][data-theme] {
  color-scheme: dark;
}
[data-ln-theme='after-hours'] {
  /* The accent is the ink; a primary action steps up to white on hover. */
  --ln-accent-light: #f2f2ef;
  --ln-accent-dark: #f2f2ef;
  --ln-accent: #f2f2ef;
  --ln-accent-hover: #ffffff;
  --ln-on-accent: #0b0b0c;
  --ln-focus: #f2f2ef;
  --ln-ember: #f2f2ef;
  --ln-on-ember: #0b0b0c;

  --ln-canvas-top: #0b0b0c;
  --ln-canvas-bottom: #0b0b0c;
  --ln-canvas: #0b0b0c;
  --ln-surface: #141416;
  --ln-surface-quiet: #1c1c1f;
  --ln-well: #101012;
  --ln-field-fill: #1c1c1f;

  /* Ink. Secondary is the muted tier (nav, ledes); quiet is the small-text
     tier at 56%, which still clears 4.5:1 on the ground. */
  --ln-ink: #f2f2ef;
  --ln-ink-secondary: #a3a3a0;
  --ln-ink-quiet: rgb(242 242 239 / 0.56);
  --ln-ink-tertiary: rgb(242 242 239 / 0.46);
  --ln-ink-placeholder: rgb(242 242 239 / 0.5);
  --ln-ink-prose: rgb(242 242 239 / 0.74);

  /* Status stays muted ink, never a fill colour for chrome. */
  --ln-positive: #9fcfb4;
  --ln-caution: #e0c48f;
  --ln-critical: #ff9b8f;
  --ln-positive-fill: #2a5e47;
  --ln-caution-fill: #6e5418;
  --ln-critical-fill: #8f3b34;
  --ln-live: #ff8a7e;
  --ln-highlight: rgb(242 242 239 / 0.22);

  --ln-hairline: rgb(255 255 255 / 0.08);
  --ln-hairline-faint: rgb(255 255 255 / 0.05);
  --ln-hairline-strong: #2a2a2d;
  --ln-control-edge: rgb(255 255 255 / 0.3);
  --ln-field-border: rgb(255 255 255 / 0.08);
  --ln-field-focus: #f2f2ef;
  --ln-scrim: rgb(0 0 0 / 0.66);

  /* Charts in ink tiers: the series that matters is bright, the rest step down. */
  --ln-series-1: #f2f2ef;
  --ln-series-2: #a3a3a0;
  --ln-series-3: #76767a;
  --ln-series-4: #58585c;
  --ln-series-5: #424246;
  --ln-series-6: #313134;
  --ln-chart-grid: rgb(255 255 255 / 0.08);
  --ln-chart-axis: rgb(242 242 239 / 0.46);
  --ln-on-media-accent: #ffffff;

  --ln-accent-wash: rgb(255 255 255 / 0.08);
  --ln-hover-wash: rgb(255 255 255 / 0.06);
  --ln-current-wash: rgb(255 255 255 / 0.14);
  --ln-answer-wash: rgb(255 255 255 / 0.08);
  --ln-selection: rgb(242 242 239 / 0.88);
  --ln-glass: rgb(11 11 12 / 0.82);
  --ln-grade-again: var(--ln-critical);
  --ln-grade-hard: var(--ln-caution);
  --ln-grade-good: var(--ln-positive);
  --ln-grade-easy: var(--ln-accent);

  /* Flat: only floating layers (menus, dialogs) keep a shadow. */
  --ln-grain: none;
  --ln-sheen: none;
  --ln-sheen-quiet: none;
  --ln-sheen-lit: none;
  --ln-lip: transparent;
  --ln-lip-lit: transparent;
  --ln-inner: none;
  --ln-e-resting: none;
  --ln-e-raised: none;
  --ln-e-floating: 0 0 0 1px rgb(255 255 255 / 0.08), 0 24px 60px rgb(0 0 0 / 0.6);
  --ln-btn-gloss: none;
  --ln-btn-lip: transparent;
  --ln-btn-shadow: none;
  --ln-btn-border: transparent;
  --ln-switch-knob-on: #0b0b0c;

  --ln-r-xs: 8px;
  --ln-r-sm: 12px;
  --ln-r-md: 14px;
  --ln-r-lg: 18px;
  --ln-r-xl: 24px;
  --ln-radius-control: 12px;
  --ln-radius-button: 999px;
  --ln-button-height: 44px;
  --ln-button-pad-block: 10px;
  --ln-button-pad-inline: 20px;
  --ln-button-size: 0.9375rem;

  --ln-font: 'Lantern After Hours Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --ln-font-ar: 'Lantern After Hours Sans', -apple-system, 'SF Arabic', 'Geeza Pro', 'Segoe UI', Tahoma, sans-serif;
  --ln-font-serif: var(--ln-font);
  --ln-lh-ar: 1.4;
  --ln-weight-strong: 560;
  --ln-weight-heavy: 560;
  /* Labels in sentence case, never uppercase or tracked; 12px is the floor. */
  --ln-label-case: none;
  --ln-label-tracking: 0;
  --ln-fs-micro: 0.75rem;
  --ln-table-head-fill: transparent;
  --ln-ease: cubic-bezier(0.16, 1, 0.3, 1);
  font-family: var(--ln-font);
  /* The page owns its ground; nothing behind it may show through in either
     mode the OS asks for. */
  background-color: #0b0b0c;
  color: var(--ln-ink);
  scrollbar-color: #3a3a3e #0b0b0c;
}
[data-ln-theme='after-hours'] ::selection {
  color: #0b0b0c;
}
[data-ln-theme='after-hours'] .ln-btn:hover:not(:disabled):not(.ln-secondary-btn, .ln-quiet-btn, .ln-quiet-destructive, .ln-destructive, .ln-positive, .ln-caution) {
  --ln-btn-fill: var(--ln-accent-hover);
}
[data-ln-theme='after-hours'] .ln-btn.ln-secondary-btn {
  --ln-btn-fill: rgb(255 255 255 / 0.08);
}
[data-ln-theme='after-hours'] .ln-btn.ln-secondary-btn:hover:not(:disabled) {
  --ln-btn-fill: rgb(255 255 255 / 0.14);
}
[data-ln-theme='after-hours'] .ln-btn:active:not(:disabled) {
  transform: scale(0.98);
}
[data-ln-theme='after-hours'] :where(h1, h2, h3, h4, strong, b, th) {
  font-weight: var(--ln-weight-strong);
}

/* ========================================================================== *
 * Site pages — a product website's layout in one calm column
 * ========================================================================== */

/* The page layer of the After Hours identity, readable under any theme since
   it reads only tokens: a single centred column with a lot of air, sections
   that open with a run-on statement (a bright heading that runs inline into a
   dimmed sentence at the same size), hairline lists instead of cards, a drawn
   stage for the real product, and one load reveal. Text sits on the open
   ground; only product imagery on the stage casts a shadow. Arabic keeps zero
   tracking and its own leading throughout. */

/* -- Layout ---------------------------------------------------------------- */
.ln-container {
  width: min(1080px, calc(100% - 64px));
  margin-inline: auto;
}
.ln-band {
  padding-top: 160px;
}
.ln-band > .ln-statement:first-child,
.ln-band > .ln-container > .ln-statement:first-child {
  margin-bottom: 56px;
}
.ln-band--close {
  padding-block: 180px 160px;
}
.ln-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 48px;
}
/* Block margins only, so a primitive can share an element with
   `.ln-container` and keep its centring. */
:is(ul, ol):is(.ln-grid, .ln-lines) {
  margin-block: 0;
  padding: 0;
  list-style: none;
}
.ln-grid--2 {
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.ln-grid--images {
  gap: 24px;
}

/* -- Type ------------------------------------------------------------------ */
.ln-statement {
  max-width: 660px;
  margin-block: 0;
  font-size: clamp(28px, 3.2vw, 40px);
  font-weight: var(--ln-weight-strong);
  line-height: 1.12;
  letter-spacing: -0.03em;
  text-wrap: pretty;
}
/* The wrapper carries the size so the space between the heading and its
   continuation is set at the statement's size, not the body's. */
.ln-statement > :is(h1, h2, h3, p) {
  display: inline;
  margin: 0;
  font: inherit;
  letter-spacing: inherit;
  color: var(--ln-ink);
}
.ln-statement > p {
  color: var(--ln-ink-tertiary);
}
.ln-statement a {
  color: var(--ln-ink);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-underline-offset: 6px;
}
.ln-statement--hero {
  max-width: 720px;
  font-size: clamp(34px, 4.6vw, 54px);
  line-height: 1.08;
  letter-spacing: -0.035em;
}
.ln-statement--page {
  max-width: 760px;
  font-size: clamp(34px, 4.4vw, 48px);
  line-height: 1.08;
  letter-spacing: -0.035em;
}
/* Inside a content page. Quiet ink is large-text only, so at 24px the
   continuation takes the small-text tier. */
.ln-statement--small {
  font-size: 24px;
  line-height: 1.25;
  letter-spacing: -0.02em;
}
.ln-statement--small > p {
  color: var(--ln-ink-quiet);
}
.ln-lede {
  max-width: 620px;
  margin-block: 22px 0;
  color: var(--ln-ink-secondary);
  font-size: 19px;
  line-height: 1.55;
}
.ln-fine {
  margin-block: 18px 0;
  color: var(--ln-ink-quiet);
  font-size: 13px;
  line-height: 1.7;
}
.ln-fine--xs {
  font-size: 12px;
}
.ln-text-link {
  color: var(--ln-ink-secondary);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--ln-ink) 30%, transparent);
  text-underline-offset: 4px;
  transition:
    color var(--ln-t-tap) var(--ln-ease),
    text-decoration-color var(--ln-t-tap) var(--ln-ease);
}
.ln-text-link:hover {
  color: var(--ln-ink);
  text-decoration-color: currentColor;
}

/* -- Actions --------------------------------------------------------------- */
.ln-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 32px;
}

/* -- Site header and footer ------------------------------------------------ */
.ln-site-header {
  position: sticky;
  top: 0;
  z-index: 20;
  height: 64px;
  background: var(--ln-glass);
  backdrop-filter: saturate(140%) blur(16px);
  -webkit-backdrop-filter: saturate(140%) blur(16px);
}
.ln-site-header-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  height: 100%;
}
.ln-site-brand {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 10px;
  color: var(--ln-ink);
  font-size: 16px;
  font-weight: var(--ln-weight-strong);
  letter-spacing: -0.02em;
  text-decoration: none;
}
.ln-site-brand > :is(img, svg) {
  width: 24px;
  height: 24px;
  border-radius: 6px;
}
.ln-site-nav {
  display: flex;
  align-items: center;
  gap: 28px;
  min-width: 0;
  color: var(--ln-ink-secondary);
  font-size: 14px;
}
.ln-site-nav a,
.ln-site-footer-links a {
  color: inherit;
  text-decoration: none;
  transition: color var(--ln-t-tap) var(--ln-ease);
}
.ln-site-nav a:not(.ln-site-nav-cta):hover,
.ln-site-nav a:not(.ln-site-nav-cta)[aria-current='page'],
.ln-site-footer-links a:hover {
  color: var(--ln-ink);
}
.ln-site-nav .ln-site-nav-cta {
  padding: 7px 14px;
  border-radius: var(--ln-r-pill);
  background: var(--ln-accent);
  color: var(--ln-on-accent);
  font-weight: var(--ln-weight-strong);
  white-space: nowrap;
}
.ln-site-nav .ln-site-nav-cta:hover {
  background: var(--ln-accent-hover, var(--ln-accent));
  color: var(--ln-on-accent);
}
.ln-site-footer {
  margin-top: 0;
  padding-block: 40px;
  border-top: 1px solid var(--ln-hairline);
  color: var(--ln-ink-quiet);
}
.ln-site-footer-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px 40px;
  padding-bottom: 32px;
}
.ln-site-footer-links {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 12px 24px;
  margin: 0;
  padding: 0;
  list-style: none;
  color: var(--ln-ink-secondary);
  font-size: 13px;
}
.ln-site-footer .ln-fine {
  margin-block: 0;
}

/* -- Hairline lists, features, FAQ ---------------------------------------- */
.ln-lines {
  display: grid;
}
.ln-lines.ln-grid {
  row-gap: 0;
}
.ln-lines > * {
  display: block;
  padding-block: 20px;
  border-top: 1px solid var(--ln-hairline);
}
.ln-lines:not(.ln-grid) > :last-child {
  border-bottom: 1px solid var(--ln-hairline);
}
.ln-lines-title {
  display: block;
  margin: 0;
  color: var(--ln-ink);
  font-size: 16px;
  font-weight: var(--ln-weight-strong);
  line-height: 1.35;
  letter-spacing: -0.01em;
}
.ln-lines-text {
  display: block;
  margin: 6px 0 0;
  color: var(--ln-ink-quiet);
  font-size: 14px;
  line-height: 1.55;
}
a.ln-lines-row {
  color: inherit;
  text-decoration: none;
}
a.ln-lines-row .ln-lines-title {
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 4px;
  transition: text-decoration-color var(--ln-t-tap) var(--ln-ease);
}
a.ln-lines-row:hover .ln-lines-title {
  text-decoration-color: currentColor;
}

.ln-feature {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.ln-feature-icon {
  width: 24px;
  height: 24px;
  margin-bottom: 18px;
  fill: none;
  stroke: var(--ln-ink);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ln-feature p,
.ln-shot-caption {
  margin: 0;
  color: var(--ln-ink-quiet);
  font-size: 15px;
  line-height: 1.55;
}
.ln-shot-caption {
  max-width: 34ch;
  margin-top: 20px;
}
:is(.ln-feature, .ln-shot-caption, .ln-lines) strong {
  color: var(--ln-ink);
  font-weight: var(--ln-weight-strong);
}
.ln-feature .ln-text-link {
  margin-top: 12px;
  font-size: 14px;
}

.ln-faq details {
  border-top: 1px solid var(--ln-hairline);
}
.ln-faq details:last-of-type {
  border-bottom: 1px solid var(--ln-hairline);
}
.ln-faq summary {
  position: relative;
  display: block;
  padding-block: 20px;
  padding-inline: 0 40px;
  color: var(--ln-ink);
  cursor: pointer;
  font-size: 16px;
  font-weight: 520;
  list-style: none;
  transition: color var(--ln-t-tap) var(--ln-ease);
}
.ln-faq summary::-webkit-details-marker {
  display: none;
}
.ln-faq summary::after {
  content: '';
  position: absolute;
  inset-inline-end: 4px;
  top: 50%;
  width: 12px;
  height: 12px;
  margin-top: -6px;
  background:
    linear-gradient(var(--ln-ink-quiet), var(--ln-ink-quiet)) center / 12px 1.5px no-repeat,
    linear-gradient(var(--ln-ink-quiet), var(--ln-ink-quiet)) center / 1.5px 12px no-repeat;
  transition: transform 0.3s var(--ln-ease);
}
.ln-faq details[open] > summary::after {
  transform: rotate(45deg);
}
.ln-faq summary:hover {
  color: var(--ln-accent-hover, var(--ln-ink));
}
.ln-faq details > :not(summary) {
  max-width: 62ch;
  margin: 0 0 24px;
  color: var(--ln-ink-secondary);
  font-size: 15px;
  line-height: 1.65;
}

/* -- Product imagery and the stage --------------------------------------- */
.ln-image {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 18px;
  box-shadow: 0 0 0 1px var(--ln-hairline);
}
.ln-stage {
  position: relative;
  overflow: hidden;
  border-radius: 24px;
  background:
    radial-gradient(42% 58% at var(--ln-stage-glow-at, 70% 40%), var(--ln-stage-glow, transparent), transparent 70%),
    linear-gradient(180deg, #151518, #0f0f11);
}
.ln-stage-bar {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 22px;
  height: 28px;
  padding-inline: 18px;
  background: rgb(255 255 255 / 0.05);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  color: var(--ln-ink-secondary);
  font-size: 13px;
  font-weight: 500;
  white-space: nowrap;
}
.ln-stage-bar-start,
.ln-stage-bar-end {
  display: flex;
  align-items: center;
  gap: 18px;
  min-width: 0;
}
.ln-stage-bar-end {
  margin-inline-start: auto;
  color: var(--ln-ink);
}
.ln-shot {
  display: block;
  max-width: none;
  height: auto;
  border-radius: var(--ln-shot-radius, 12px);
  box-shadow:
    0 0 0 1px rgb(255 255 255 / 0.1),
    0 30px 80px rgb(0 0 0 / 0.6);
}
/* The page's one entrance: the product drops open once on load. */
.ln-reveal {
  animation: ln-reveal 0.7s cubic-bezier(0.16, 1, 0.3, 1) var(--ln-reveal-delay, 0.2s) both;
}
@keyframes ln-reveal {
  from {
    clip-path: inset(0 0 100% 0 round var(--ln-shot-radius, 12px));
    transform: translateY(-4px);
  }
  to {
    clip-path: inset(0 0 0 0 round var(--ln-shot-radius, 12px));
    transform: none;
  }
}

/* -- Long-form pages ------------------------------------------------------- */
.ln-article {
  max-width: 700px;
  color: var(--ln-ink-prose, var(--ln-ink));
  font-size: 17px;
  line-height: 1.7;
}
.ln-article :is(h2, h3, h4, strong, th) {
  color: var(--ln-ink);
  font-weight: var(--ln-weight-strong);
}
.ln-article h2 {
  margin: 56px 0 14px;
  font-size: 26px;
  line-height: 1.25;
  letter-spacing: -0.02em;
  text-wrap: balance;
}
.ln-article h3 {
  margin: 32px 0 8px;
  font-size: 17px;
  line-height: 1.35;
  letter-spacing: -0.01em;
}
.ln-article a:not(.ln-btn) {
  color: var(--ln-ink);
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--ln-ink) 35%, transparent);
  text-underline-offset: 3px;
}
.ln-article a:not(.ln-btn):hover {
  text-decoration-color: currentColor;
}
.ln-article :is(ul, ol) {
  padding-inline-start: 24px;
}
.ln-article li + li {
  margin-top: 8px;
}
.ln-article li::marker {
  color: var(--ln-ink-quiet);
}
.ln-article :not(pre) > code {
  padding: 1px 6px;
  border-radius: 6px;
  background: var(--ln-surface-quiet);
  color: var(--ln-ink);
  font-size: 0.86em;
}
.ln-article pre {
  overflow-x: auto;
  margin: 16px 0;
  padding: 16px 18px;
  border-radius: 12px;
  background: var(--ln-surface);
  font-size: 13px;
  line-height: 1.55;
}
.ln-article table {
  width: 100%;
  margin: 16px 0;
  border-collapse: collapse;
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.ln-article :is(th, td) {
  padding-block: 10px;
  padding-inline: 0 12px;
  border-bottom: 1px solid var(--ln-hairline);
  text-align: start;
  vertical-align: top;
}
.ln-article caption,
.ln-article figcaption {
  padding-bottom: 8px;
  color: var(--ln-ink-quiet);
  font-size: 13px;
  text-align: start;
}
.ln-article figcaption {
  padding: 12px 0 0;
}
.ln-article blockquote {
  margin: 24px 0;
  padding-inline-start: 20px;
  border-inline-start: 1px solid var(--ln-hairline-strong);
  color: var(--ln-ink-secondary);
}
.ln-article hr {
  margin: 48px 0;
  border: 0;
  border-top: 1px solid var(--ln-hairline);
}

/* -- Arabic: no tracking, taller lines ------------------------------------ */
:is(.ln-statement, .ln-site-brand, .ln-lines-title, .ln-article h2, .ln-article h3):lang(ar) {
  letter-spacing: 0;
}
/* Plex Arabic reads larger than Hanken at the same size, so Arabic
   statements set about 0.85x to keep the same weight on the page. */
.ln-statement:lang(ar) {
  font-size: clamp(25px, 2.8vw, 34px);
  line-height: 1.35;
}
.ln-statement--hero:lang(ar) {
  font-size: clamp(30px, 3.9vw, 44px);
  line-height: 1.3;
}
.ln-statement--page:lang(ar) {
  font-size: clamp(30px, 3.7vw, 40px);
  line-height: 1.3;
}
.ln-statement--small:lang(ar) {
  font-size: 22px;
}
:is(.ln-lede, .ln-feature p, .ln-shot-caption, .ln-lines-text, .ln-faq details > :not(summary)):lang(ar) {
  line-height: 1.8;
}
.ln-article:lang(ar) {
  line-height: 1.85;
}

/* -- Breakpoints ---------------------------------------------------------- */
@media (max-width: 960px) {
  .ln-grid:not(.ln-grid--2, .ln-grid--images) {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .ln-grid.ln-grid--stack-960 {
    grid-template-columns: minmax(0, 1fr);
  }
}
@media (max-width: 680px) {
  .ln-container {
    width: calc(100% - 40px);
  }
  .ln-band {
    padding-top: 104px;
  }
  .ln-band > .ln-statement:first-child,
  .ln-band > .ln-container > .ln-statement:first-child {
    margin-bottom: 36px;
  }
  .ln-band--close {
    padding-block: 120px 104px;
  }
  .ln-grid,
  .ln-grid:not(.ln-grid--2, .ln-grid--images) {
    grid-template-columns: minmax(0, 1fr);
    row-gap: 40px;
  }
  .ln-lines.ln-grid {
    row-gap: 0;
  }
  .ln-lede {
    font-size: 17px;
  }
  .ln-site-header {
    height: 56px;
  }
  .ln-site-nav {
    gap: 16px;
  }
  .ln-site-nav > a:not(.ln-site-nav-cta, .ln-site-nav-keep) {
    display: none;
  }
  .ln-site-footer-row {
    flex-direction: column;
    align-items: flex-start;
    gap: 20px;
  }
  .ln-site-footer-links {
    justify-content: flex-start;
  }
  .ln-stage {
    border-radius: 18px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .ln-reveal {
    animation: none;
  }
}

/* ========================================================================== *
 * Layout helpers
 * ========================================================================== */

/* Each size is a complete stack, not a modifier that needs `.ln-stack` beside
   it — a gap with no flex container is a silent no-op, and it was one. */
.ln-stack,
.ln-stack-sm,
.ln-stack-md,
.ln-stack-xl {
  display: flex;
  flex-direction: column;
}
.ln-stack {
  gap: var(--ln-lg);
}
.ln-stack-sm {
  gap: var(--ln-sm);
}
.ln-stack-md {
  gap: var(--ln-md);
}
.ln-stack-xl {
  gap: var(--ln-xl);
}
.ln-hstack {
  display: flex;
  align-items: center;
  gap: var(--ln-sm);
}
.ln-hstack-wrap {
  flex-wrap: wrap;
}
.ln-spacer {
  flex: 1;
}
/* Page margins for a scrolling reading surface. */
.ln-page {
  max-width: var(--ln-page-width, 860px);
  margin: 0 auto;
  padding: var(--ln-xl) var(--ln-lg);
}
/* A page shell that keeps the footer at the foot of the window on a short
   page: put it on `body` (or a wrapper), and `main` or `.ln-shell-main` takes
   the spare height. Opt-in, because a flex column changes how children's
   margins behave. */
.ln-shell {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
}
.ln-shell > :is(main, .ln-shell-main) {
  flex: 1 0 auto;
}
.ln-shell > * {
  min-width: 0;
}
/* Auto margins in a flex column shrink an item to its content; a page column
   should still fill up to its max-width. */
.ln-shell > .ln-page {
  width: 100%;
}
.ln-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* Thin scrollbars inside the canvas; their colour is set at the root. */
.ln-canvas * {
  scrollbar-width: thin;
}

/* Arabic Subtitles under Lantern's After Hours theme (data-ln-theme on <html>).
   Lantern's page layer owns the shared pieces: container, bands, run-on statements,
   hairline lists, features, FAQ, stage, shot, reveal, article, header and footer.
   This sheet styles only the site's own things: the drop target and the app's states,
   the browser window drawn around the stage's captures, the SRT excerpt, the pricing rows, the
   benchmark figure, the editor and the long-form extras. No hue: colour on this page
   comes only from the sample it shows, and the sample is text. */

:root{
  --site-mono:var(--ln-font-mono);
  --site-ease:cubic-bezier(.16,1,.3,1);
}

*{box-sizing:border-box}
html,body{background:#0b0b0c}
html{scroll-padding-top:88px}
body{margin:0;min-height:100vh;display:flex;flex-direction:column;overflow-x:clip}
main{flex:1 0 auto}
h1,h2,h3,p{margin-top:0}
h1,h2,h3{overflow-wrap:anywhere;min-width:0;text-wrap:balance}
a{color:inherit}
button svg{pointer-events:none}
[hidden]{display:none!important}
::selection{background:rgb(242 242 239 / .88);color:#0b0b0c}
:focus-visible{outline:2px solid var(--ln-focus);outline-offset:4px;border-radius:4px}
.skip:focus{position:fixed;inset-inline-start:16px;top:12px;width:auto;height:auto;clip-path:none;padding:10px 14px;background:var(--ln-surface);border-radius:8px;z-index:60}
/* Arabic joins its letters; tracking would pull them apart. */
:lang(ar){letter-spacing:0}

/* ---- header and footer: the brand mark, drawn in ink ---- */
.brand-mark{fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.language-switch{font-family:var(--ln-font-ar)}
.language-switch:lang(en){font-family:var(--ln-font)}
.ln-site-footer .powered{color:inherit;text-decoration:none}
.ln-site-footer .powered:hover{color:var(--ln-ink)}
.analytics-settings{padding:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer}
.analytics-settings:hover{color:var(--ln-ink)}
.analytics-consent{position:fixed;inset-inline:16px;bottom:16px;z-index:40;width:min(560px,calc(100% - 32px));margin-inline:auto;display:grid;gap:16px;padding:20px;border-radius:18px;background:var(--ln-surface-quiet)}
.analytics-consent p{margin:6px 0 0;color:var(--ln-ink-secondary)}
.analytics-consent:focus{outline:none}
.analytics-consent a{color:var(--ln-ink);text-decoration:underline;text-decoration-color:rgb(242 242 239 / .3);text-underline-offset:4px}
.analytics-consent .analytics-state{margin-top:10px;color:var(--ln-ink);font-weight:var(--ln-weight-strong)}
.analytics-state::before{content:'';display:inline-block;width:.55em;height:.55em;margin-inline-end:.45em;border-radius:50%;background:var(--ln-ink)}
.analytics-state[data-state=off]::before{background:var(--ln-ink-tertiary)}
.analytics-consent-actions{display:flex;flex-wrap:wrap;gap:10px;justify-content:flex-end}
.analytics-consent-actions .ln-btn{white-space:nowrap}
@media(max-width:480px){.analytics-consent-actions .ln-btn{flex:1 1 auto}}

/* ---- the app: the run-on statement, then the drop target ---- */
.app{padding-block:48px 0}
.checkout-return{margin:0 0 24px}
.app-statement{margin-bottom:40px}
.app-statement .sample-link{white-space:nowrap}
.app-lede{max-width:620px;margin:-16px 0 32px;color:var(--ln-ink-secondary);font-size:17px;line-height:1.6}
.app-lede a{color:var(--ln-ink);text-decoration:underline;text-decoration-color:rgb(242 242 239 / .3);text-underline-offset:4px}

/* A large, quiet invitation on the ground: a hairline dash, no fill of its own.
   The whole zone opens the picker (app.js); its button is the keyboard control. */
.drop{
  --ln-well:#0b0b0c;
  --ln-drop-border:rgb(255 255 255 / .16);
  --ln-drop-radius:24px;
  --ln-drop-pad:clamp(36px,4.5vw,56px);
  min-height:clamp(220px,28vh,280px);justify-content:center;cursor:pointer;gap:14px;
}
.checker-drop{--ln-well:#0b0b0c;--ln-drop-border:rgb(255 255 255 / .16)}
:is(.drop,.checker-drop)>.ln-drop-glyph{width:32px;height:32px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;color:var(--ln-ink-secondary)}
.drop .drop-title{font-size:17px;color:var(--ln-ink);text-wrap:balance}
.drop .choose-file{min-width:min(100%,15rem)}
.drop-over-label{display:none}
.drop[data-over] .drop-idle{display:none}
.drop[data-over] .drop-over-label{display:inline}
.drop-meta{max-width:76ch;line-height:1.7;text-wrap:balance}
.drop-meta strong{color:var(--ln-ink-secondary);font-weight:var(--ln-weight-strong);white-space:nowrap}
.drop-meta-part{white-space:nowrap}
.drop-meta-part:last-child{white-space:normal}
@media (prefers-reduced-motion:no-preference){
  .drop>.ln-drop-glyph{transition:transform .3s var(--site-ease)}
  .drop[data-over]>.ln-drop-glyph{transform:translateY(-4px)}
}
/* Once files are listed the zone is one row: drop more, or choose more. */
.drop.ln-compact{min-height:0;cursor:default}
.drop.ln-compact .drop-meta{display:none}
.drop.ln-compact>.ln-drop-glyph{width:22px;height:22px}
.drop.ln-compact .drop-title{font-size:15px}
.app:has(.drop.ln-compact) :is(.drop-refill,.drop-privacy,.before-picker){display:none}
/* Touch screens cannot drag a file in: the button is the whole action. */
@media (hover:none) and (pointer:coarse){
  .drop .drop-title{display:none}
  .drop:not(.ln-compact) .choose-file{width:100%;max-width:22rem;min-height:52px;font-size:16px}
  .drop.ln-compact .choose-file{flex:1}
}
@media (max-width:680px){.drop{--ln-drop-pad:36px;--ln-drop-radius:18px;min-height:0}}

/* Under the zone, small and dim: the refill, the way back into a minute bank, privacy. */
.drop-after{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:6px 24px;margin-block-start:16px;font-size:13px;line-height:1.7;color:var(--ln-ink-quiet)}
.drop-refill{margin:0;color:var(--ln-ink-quiet);font-size:13px}
.drop-refill strong{color:var(--ln-ink-secondary);font-weight:var(--ln-weight-strong)}
.drop-refill a{white-space:nowrap}
.drop-privacy{flex-basis:100%;margin:0}
.bank-access-inline{margin:0;padding:0}
.bank-access-inline>summary{color:var(--ln-ink-secondary);font-size:13px}
.bank-access-inline[open]{flex-basis:100%}
.bank-access-body{display:grid;gap:12px;max-width:560px;padding-block:8px 16px}
.bank-access-body>p{margin:0}
/* Turnstile's widget takes no room until a visitor has to answer it. */
#bank-access-form{position:relative}
.bank-access-turnstile:not(.is-interactive){position:absolute;inset-inline:0;block-size:0;overflow:hidden}
.bank-access-turnstile.is-interactive{padding-block-start:10px}
.bank-access-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:stretch;gap:10px}
.bank-access-row .ln-input{min-width:0;width:100%}
.bank-access-row .ln-btn{white-space:nowrap}
.bank-access .ln-field-label{font-size:13px}
.bank-access-status{padding-block-start:4px}
@media (max-width:680px){.bank-access-row{grid-template-columns:1fr}}

/* ---- the app's states: progress, rows, the pay bar ---- */
.availability-note{margin-top:20px}
.stages{display:grid;gap:6px;margin:32px 0 16px}
.stage-detail{margin:0;max-width:70ch;color:var(--ln-ink-secondary);line-height:1.5}
.files{margin-top:24px}
.row-price{color:var(--ln-ink-secondary);font-size:14px;padding-inline-end:4px}
.ln-file-row>.row-downloads{grid-column:1/-1;display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:6px}
.row-downloads-label{flex-basis:100%;color:var(--ln-ink-secondary);font-size:13px;font-weight:var(--ln-weight-strong)}
.ln-file-row>.row-downloads>.row-downloads-head{flex-basis:100%;display:flex;align-items:center;gap:10px}
.row-downloads-head>.row-downloads-label{flex:0 0 auto}
.row-download,.editor-download{display:inline-flex;align-items:center;gap:6px}
.row-format.ln-select{display:inline-block;width:auto;min-height:36px;padding-block:4px;padding-inline-start:10px;font-size:13px}
.row-track{display:grid;gap:10px;grid-column:1/-1;min-width:0;margin-top:6px}
.row-track>label{display:grid;gap:6px;min-width:0}
.row-track select{width:100%;min-width:0}
.row-track p{margin:0}
.row-track button{justify-self:start;min-height:44px;max-width:100%;white-space:normal}
/* A name's own script picks the isolate's direction, but the pair stays left-to-right
   so an appended `.en.srt` never jumps in front of it. */
.ln-file-row>.ln-file-name{display:flex;overflow:hidden;white-space:nowrap;unicode-bidi:isolate;direction:ltr}
.ln-file-row:dir(ltr)>.ln-file-name{justify-content:flex-start}
.ln-file-row:dir(rtl)>.ln-file-name{justify-content:flex-end}
.ln-file-name-base{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;flex:0 1 auto}
.ln-file-name-ext{flex:0 0 auto;white-space:nowrap}
.duplicate-note{margin:10px 0 0;color:var(--ln-ink-secondary)}
@media (max-width:680px){
  .ln-file-row>.row-downloads{display:grid;grid-template-columns:1fr 1fr}
  .row-downloads-label,.ln-file-row>.row-downloads>.row-downloads-head{grid-column:1/-1}
  .ln-file-row>.row-downloads>.ln-btn:not(.ln-quiet-btn){grid-column:1/-1;width:100%}
  .ln-file-row>.row-downloads>.ln-btn.ln-quiet-btn{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
  .ln-file-row:not([data-state=done])>.ln-file-actions{grid-column:2;grid-row:1}
  body[data-workflow=arabic] .ln-file-row:not([data-state=uploading])>.ln-file-meta{grid-column:2;grid-row:2;justify-self:end;margin:0}
  .ln-file-row{padding:12px 16px}
}

/* The pay bar is the form, so it keeps a raised field fill; it casts no shadow. */
.paybar{--ln-radius:18px;margin-top:24px;padding:24px;display:grid;gap:16px;box-shadow:none}
.paybar-head{display:flex;align-items:baseline;justify-content:space-between;gap:24px}
.paybar-head .ln-caption{color:var(--ln-ink-secondary)}
.paybar-head strong{white-space:nowrap;font-size:24px;letter-spacing:-.02em}
.paybar-head strong:lang(ar){letter-spacing:0}
.paybar-note{color:var(--ln-ink-quiet);margin:0;text-align:center}
.paybar-balance{margin:-12px 0 0;text-align:end;color:var(--ln-ink);font-weight:var(--ln-weight-strong)}
#pay-express:not([hidden]):not(:empty){margin-bottom:4px}
.quote-rows{margin:0;display:grid}
.quote-rows>div{display:flex;align-items:baseline;justify-content:space-between;gap:16px;padding-block:8px;border-block-end:1px solid var(--ln-hairline)}
.quote-rows>div:last-child{border-block-end:0}
.quote-rows dt{color:var(--ln-ink-secondary);font-size:14px}
.quote-rows dd{margin:0;color:var(--ln-ink);font-size:14px;text-align:end;white-space:nowrap;font-variant-numeric:tabular-nums}
.quote-rows .quote-charge dt,.quote-rows .quote-charge dd{color:var(--ln-ink);font-weight:var(--ln-weight-strong)}
.quote-notes{margin:10px 0 0;color:var(--ln-ink-quiet);line-height:1.5}
.quote-notes a{color:var(--ln-ink);text-decoration:underline;text-underline-offset:4px}
.payment-status,.free-check-status{margin-block:12px;padding:14px 16px;border:1px solid var(--ln-hairline);border-radius:12px;background:var(--ln-well)}
.payment-status p,.free-check-status p{margin-bottom:10px;line-height:1.6}
.free-offer{display:grid;gap:10px;padding-block-start:16px;border-block-start:1px solid var(--ln-hairline)}
.free-offer>p{margin:0;color:var(--ln-ink-secondary)}
.free-offer-title{font-weight:var(--ln-weight-strong)}
.free-offer .ln-meter{margin-block-start:4px}
.free-turnstile:empty{display:none}
.sample-note{margin:10px 0 0;line-height:1.6}
#sample-button{margin-top:12px;white-space:normal;max-width:100%}
.ln-banner.payment-success{flex-wrap:wrap;margin-top:16px}
.ln-banner.payment-success>*{flex:1 1 24ch}
.bank-status{margin:12px 0 0;color:var(--ln-ink-secondary)}

/* ---- translation: the direction is chosen first ---- */
.workflow-controls{min-inline-size:0;max-width:640px;margin:0 0 32px;padding:0;border:0}
.workflow-controls>legend{float:inline-start;width:100%;padding:0;margin-block-end:10px;font-size:17px;font-weight:var(--ln-weight-strong)}
.workflow-controls>legend~*{clear:both}
.workflow-controls.collapsed>*:not(legend):not(.translation-summary){display:none}
.workflow-controls .ln-control-label{display:grid;gap:6px;min-width:0;margin-block:14px}
.translation-summary{margin:0;color:var(--ln-ink-secondary);clear:both}
.workflow-controls #translation-continue{width:100%;margin-block-start:10px}
/* Selectable options: a raised fill and a 14px radius; the edge goes to ink when chosen. */
.direction-cards{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:10px}
.direction-card{display:flex;align-items:flex-start;gap:12px;min-inline-size:0;padding:14px 16px;border:1px solid var(--ln-hairline);border-radius:14px;background:var(--ln-surface-quiet);cursor:pointer;transition:border-color .2s var(--site-ease)}
@media (hover:hover){.direction-card:hover{border-color:rgb(255 255 255 / .2)}}
.direction-card:has(input:checked){border-color:var(--ln-ink)}
.direction-card:has(input:focus-visible){outline:2px solid var(--ln-focus);outline-offset:2px}
.direction-card:has(input:disabled){opacity:.55;cursor:not-allowed}
.direction-card input{accent-color:var(--ln-ink);margin-top:4px}
.direction-card span{display:grid;gap:4px;min-width:0;overflow-wrap:anywhere}
.direction-card strong{font-weight:var(--ln-weight-strong)}
.direction-card small{color:var(--ln-ink-quiet);font-size:13px;line-height:1.45}
@media (max-width:680px){.direction-cards{grid-template-columns:1fr}}

/* ---- the stage: the editor with the example file, in a drawn browser window ---- */
/* Only the window bar is drawn; everything inside it is a capture of the app (stage.mjs). */
.home-stage{padding-top:24px}
.sub-stage{padding:44px 0 56px}
.sub-window{--ln-shot-radius:12px;width:min(880px,calc(100% - 64px));margin-inline:auto;overflow:hidden;background:#0b0b0c}
.sub-window-bar{position:relative;display:flex;align-items:center;height:32px;padding-inline:12px;background:rgb(255 255 255 / .05);border-block-end:1px solid rgb(255 255 255 / .06)}
.sub-window-lights{display:flex;gap:7px}
.sub-window-lights i{width:11px;height:11px;border-radius:50%;background:rgb(255 255 255 / .16)}
.sub-window-address{position:absolute;inset-inline:0;text-align:center;font-size:12px;color:var(--ln-ink-quiet);pointer-events:none}
.sub-window-shot img{display:block;width:100%;height:auto}
.stage-foot{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;gap:8px 32px}
.stage-foot .ln-shot-caption{max-width:52ch}
.stage-downloads{margin:20px 0 0;white-space:nowrap}
@media (max-width:680px){
  .home-stage{padding-top:80px}
  .sub-stage{padding:24px 0 32px}
  .sub-window{width:min(320px,calc(100% - 40px))}
  .stage-downloads{white-space:normal;margin-top:0}
}

/* ---- what you get: the file, then the facts beside it ---- */
.app-notes .deliverable{align-items:start}
.srt-sample{margin:0;min-width:0}
.srt-file{margin:0;padding:20px 22px;overflow-x:auto;border-radius:14px;background:var(--ln-surface);font:400 14px/1.6 var(--site-mono);color:var(--ln-ink-secondary);text-align:left;white-space:pre}
.srt-file code{font:inherit}
.srt-index,.srt-time{color:var(--ln-ink-quiet);font-variant-numeric:tabular-nums}
.srt-text{display:inline-block;width:100%;text-align:right;color:var(--ln-ink);font-family:var(--ln-font-ar);font-size:16px;unicode-bidi:isolate;white-space:normal;letter-spacing:0}
.srt-text-ltr{text-align:left;font-family:var(--ln-font)}
.srt-sample figcaption{margin-block-start:12px;max-width:52ch}
.srt-pair{display:grid;gap:16px;min-width:0}
.srt-pair .srt-sample figcaption.srt-label{margin:0 0 8px;color:var(--ln-ink-secondary);font-size:13px;font-weight:var(--ln-weight-strong)}
.srt-pair-note{margin:0;max-width:52ch}
.deliverable.no-sample{grid-template-columns:minmax(0,1fr);max-width:44rem}
.facts{margin:0}
.facts dd{margin-inline:0}
.facts>.free-reassurance .ln-lines-text{color:var(--ln-ink-secondary)}
.notes-links,.notes-guides{display:flex;flex-wrap:wrap;gap:6px 20px;margin:20px 0 0}
.notes-guides a{color:var(--ln-ink-secondary);text-decoration:underline;text-decoration-color:rgb(242 242 239 / .3);text-underline-offset:4px;white-space:nowrap}
.notes-guides a:hover{color:var(--ln-ink)}
.translation-faq{margin-top:40px}
.translation-faq-title{margin:0 0 8px;font-size:17px}

/* ---- for editors: four features, each a title over a dim line ---- */
.pro-item-title{margin:0 0 6px;font-size:16px;line-height:1.35;letter-spacing:-.01em}
.pro-item-title:lang(ar){letter-spacing:0}
.pro-list p{max-width:46ch}

/* ---- the benchmark: the measured rows beside who the product is for ---- */
.wer{margin:0}
.wer figcaption h3{margin:0 0 4px;font-size:17px}
.wer figcaption p{margin:0;color:var(--ln-ink-quiet);font-size:14px}
.wer figcaption p span{display:block}
.wer-rows{margin-top:24px}
.wer-row>.ln-meter-label{unicode-bidi:isolate}
.wer-caption{margin-top:24px}
.why-meaning{margin:0 0 24px;color:var(--ln-ink-quiet);font-size:15px;line-height:1.55}
.why-meaning strong{color:var(--ln-ink);font-weight:var(--ln-weight-strong)}
.dialect-list{margin:0;padding:0;list-style:none;border-block-start:1px solid var(--ln-hairline)}
.dialect{padding-block:10px;border-block-end:1px solid var(--ln-hairline);color:var(--ln-ink-secondary);font-size:14px;line-height:1.5}
.dialect-name{unicode-bidi:isolate}

/* ---- pricing ---- */
.pricing-grid{margin-top:56px;align-items:start}
.pricing-offer{display:flex;justify-content:space-between;gap:16px}
.pricing-offer .ln-digits{font-variant-numeric:tabular-nums}
.first-purchase{max-width:60ch}
.first-purchase h2{margin:0 0 12px;font-size:24px;line-height:1.25;letter-spacing:-.02em}
.first-purchase h2:lang(ar){letter-spacing:0}
.first-purchase>p{margin:0 0 14px;color:var(--ln-ink-secondary);line-height:1.65}
.first-purchase>.ln-fine{margin:0 0 10px}
.quote-example{max-width:26rem;margin-block:16px 20px;border-block:1px solid var(--ln-hairline)}
.bank-access-page{display:grid;gap:12px;max-width:560px;margin-top:96px;padding-top:32px;border-top:1px solid var(--ln-hairline)}
.bank-access-page h2{margin:0;font-size:24px;letter-spacing:-.02em}
.bank-access-page h2:lang(ar){letter-spacing:0}
.bank-access-page>p{margin:0}
.price-close .ln-fine{max-width:62ch}

/* The last band on an app page leaves room above the footer. */
.band-end{padding-bottom:120px}
@media (max-width:680px){.band-end{padding-bottom:80px}}

/* ---- long-form pages: guides, help, legal, the checker ---- */
.page{padding-block:72px 120px}
.page-title{margin-bottom:28px}
.page .ln-lede{margin-block:0 48px}
.page-title+.ln-article,.page-title+.ln-lede+.ln-article{margin-top:0}
.ln-article>:first-child{margin-top:0}
.help-faq{margin-block:8px 56px}
.help-more{margin-top:56px}
.guide-links ul{padding-inline-start:24px}
.ln-article .ln-actions{margin-top:40px}
.guide-hub-title{margin:96px 0 20px;font-size:24px;line-height:1.25;letter-spacing:-.02em}
.guide-hub-title:lang(ar){letter-spacing:0}
.guide-index-link{display:block}
.guide-index-text{max-width:52ch}
/* A closing action inside an article: a hairline above, never a filled card. */
.guide-cta{margin-block:72px 24px;padding-top:32px;border-top:1px solid var(--ln-hairline)}
.ln-article .guide-cta h2{margin-top:0}
.guide-cta p{max-width:56ch}
.guide-cta .ln-btn{display:inline-flex;margin-top:8px;white-space:nowrap}
.hub-cta{margin-top:120px;padding-top:0;border-top:0}
.guide-provenance{margin-block:72px 0;padding-block-start:16px;border-block-start:1px solid var(--ln-hairline);color:var(--ln-ink-quiet);font-size:13px}
.guide-provenance a{color:inherit}
.guide-sources a{overflow-wrap:anywhere}
.guide-faq .ln-details{padding-block:10px;border-block-end:1px solid var(--ln-hairline)}
.guide-faq .ln-details:first-of-type{border-block-start:1px solid var(--ln-hairline)}
.guide-article .ln-scroll-x{margin-block:24px;overflow-x:auto}
.guide-article .ln-table{min-width:38rem;margin:0}
/* A list to tick off: an empty box in place of each bullet. */
.guide-article .guide-checklist{list-style:none;padding-inline-start:0}
.guide-checklist li{position:relative;padding-inline-start:1.9em}
.guide-checklist li::before{content:"";position:absolute;inset-inline-start:0;top:.4em;width:1em;height:1em;border:1.5px solid var(--ln-ink-quiet);border-radius:4px}
.dialect-landing .guide-links{margin-top:56px;padding-block-start:24px;border-block-start:1px solid var(--ln-hairline)}
.legal h3{margin-top:32px}
.market-direction{padding-block:12px;border-block:1px solid var(--ln-hairline);color:var(--ln-ink);font-weight:var(--ln-weight-strong)}
.market-links{display:flex;flex-wrap:wrap;gap:10px 32px}
.language-catalog{max-width:860px}
.language-catalog-list,.language-target-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 32px;padding:0!important;list-style:none}
.language-catalog-list li,.language-target-list li{display:grid;grid-template-columns:auto 1fr;align-items:baseline;gap:12px;margin:0!important;padding-block:12px;border-block-end:1px solid var(--ln-hairline)}
.language-target-list li{grid-template-columns:1fr auto}
.language-choice{display:grid;gap:2px;min-width:0;text-decoration:none!important}
.language-choice:hover .language-native{text-decoration:underline;text-underline-offset:4px}
.language-rank{color:var(--ln-ink-quiet);font-variant-numeric:tabular-nums}
.language-native{color:var(--ln-ink);font-weight:var(--ln-weight-strong);justify-self:start}
.language-english{justify-self:start;color:var(--ln-ink-quiet);font-size:13px}
@media (max-width:680px){.language-catalog-list,.language-target-list{grid-template-columns:1fr}}

/* /arabic-srt/: the tool first, then the steps and the sample file it describes. */
.srt-guide .srt-sample{margin-block:24px 16px}
.srt-download{display:flex;flex-wrap:wrap;align-items:center;gap:10px 16px}
.srt-download .ln-caption{overflow-wrap:anywhere;color:var(--ln-ink-quiet)}
.srt-workflow .ln-steps{margin-block-start:16px}
.srt-choices{list-style:none;margin:20px 0 0!important;padding:0!important;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 32px}
.srt-choices li{display:grid;align-content:start;gap:4px;margin:0!important;padding-block:16px;border-block-start:1px solid var(--ln-hairline)}
.srt-choices span{color:var(--ln-ink-quiet);font-size:15px;line-height:1.5}
@media (max-width:680px){.srt-choices{grid-template-columns:1fr}}
.srt-check{margin-block:0 24px;white-space:pre-wrap;overflow-wrap:anywhere;text-align:left}
.srt-guide p code,.srt-guide li code{unicode-bidi:isolate;white-space:nowrap}

/* ---- the editor ---- */
/* The editor takes over the page; the sections below it would otherwise scroll into view. */
body.editing :is(.section,.app-notes,.home-stage,.price-close){display:none}
.editor{padding-block:32px 96px}
#player:not([src]){display:none}
@media (min-width:681px){.preview:not(.empty){aspect-ratio:auto;height:min(52vh,518px)}.preview:not(.empty) video{position:absolute;inset:0}}
.editor-top{display:flex;align-items:center;gap:16px;margin-bottom:24px}
#editor-back{white-space:nowrap}
.editor-top h2{flex:1;margin:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:24px;letter-spacing:-.02em}
.editor-top h2:lang(ar){letter-spacing:0}
#editor-title:focus{outline:none}
.editor-title-name{unicode-bidi:isolate;direction:ltr}
.editor-title-ext{white-space:nowrap}
.editor-top .ln-caption{color:var(--ln-ink-quiet);white-space:nowrap}
.editor-top .editor-warnings{white-space:nowrap}
[dir=rtl] #editor-title{text-align:right}
.preview{position:relative;background:#000;border-radius:14px;overflow:hidden;aspect-ratio:16/9;display:grid;place-items:center}
.preview video{width:100%;height:100%;object-fit:contain;background:#000}
#preview-placeholder{position:absolute;inset:0;display:grid;place-items:center;align-content:center;gap:16px;padding:24px;text-align:center;color:var(--ln-ink-secondary)}
#preview-placeholder p{margin:0;max-width:34ch}
.preview.empty{aspect-ratio:auto;display:block;background:var(--ln-surface)}
.preview.empty #preview-placeholder{position:static;width:100%;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;text-align:start;padding:16px 20px}
#caption-preview{position:absolute;inset-inline:0;bottom:24px;text-align:center;color:#fff;font-size:24px;text-shadow:0 1px 2px rgb(0 0 0 / .9),0 0 12px rgb(0 0 0 / .6);padding-inline:24px;white-space:pre-line}
.editor-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:10px;margin-block:24px}
.editor-toolbar .ln-btn{white-space:nowrap}
.editor-toolbar .speed{margin-inline-start:auto;display:flex;align-items:center;gap:10px;margin-block:0;white-space:nowrap}
.preview.empty~.editor-toolbar .speed{display:none}
.editor-retention{margin:-12px 0 16px;color:var(--ln-ink-quiet)}
.cues{display:grid;gap:10px}
.cue-row{display:flex;gap:16px;padding:16px;align-items:start}
.cue-row.active{outline:2px solid var(--ln-ink);outline-offset:-2px}
.cue-head{display:flex;flex-direction:column;align-items:center;gap:6px;flex-shrink:0;width:64px}
.cue-index{flex-shrink:0;font-variant-numeric:tabular-nums}
.cue-edited,.cue-speaker{font-size:12px;white-space:nowrap}
.cue-timing{display:grid;gap:6px;flex-shrink:0;width:120px}
.cue-timing .ln-input{width:100%}
.cue-timing .ln-field-label{white-space:nowrap}
.cue-body{flex:1;min-width:0;display:grid;gap:6px}
.cue-body .ln-textarea{min-height:64px;width:100%}
.cue-actions{display:flex;gap:10px}
.cue-warnings{margin:6px 0 0;padding-inline-start:20px;color:var(--ln-caution);font-size:13px}
.cue-warnings:empty{display:none}
@media (max-width:680px){
  .editor{padding-block-start:12px}
  .editor-top{flex-wrap:wrap;gap:6px 16px;margin-bottom:16px}
  .editor-top h2{order:3;flex-basis:100%;white-space:normal;font-size:19px;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;line-clamp:2}
  .editor-top .ln-caption{margin-inline-start:auto}
  .preview:not(.empty){aspect-ratio:auto;max-height:36vh}
  .preview.empty #preview-placeholder{padding:12px 16px;gap:10px}
  .editor-toolbar{margin-block:16px}
  .editor-toolbar .ln-btn{padding-inline:16px}
  .editor-toolbar .editor-download{margin-inline-start:auto}
  .editor-toolbar .speed{margin-inline-start:0;width:100%}
  .cue-row{display:grid;grid-template-columns:56px minmax(0,1fr);gap:6px 10px;padding:12px}
  .cue-head{grid-row:1;width:auto}
  .cue-timing{grid-column:2;grid-row:1;width:auto;grid-template-columns:1fr 1fr;gap:6px}
  .cue-timing .ln-field-label{font-size:12px}
  .cue-timing .ln-input{min-height:36px;padding-block:4px}
  .cue-body{grid-column:1/-1}
  .cue-body .ln-textarea{min-height:48px}
}
@media (max-width:359px){.editor-toolbar .editor-download{flex-basis:100%;margin-inline-start:0}.editor-download #download{flex:1}}

/* /tools/arabic-srt-checker/. Lantern supplies the components (drop zone, banner, table, pills,
   disclosures); these rules only place them, and are scoped to the checker's own classes. */

.srt-checker{padding-block:var(--ln-lg) var(--ln-xl)}
.checker-lede{max-width:62ch;margin-bottom:var(--ln-lg);color:var(--ln-ink-secondary)}

/* The drop zone: the zone opens the picker, its button is the keyboard control. */
.checker-drop{--ln-drop-pad:clamp(32px,6vw,56px);justify-content:center;min-height:clamp(200px,30vh,260px);cursor:pointer}
.checker-drop .ln-btn{min-width:min(100%,15rem);margin-block:var(--ln-xs)}
.checker-drop .ln-drop-title{text-wrap:balance}
.checker-drop .ln-drop-meta{max-width:60ch;line-height:1.6;text-wrap:balance}
.checker-over{display:none}
.checker-drop[data-over] .checker-idle{display:none}
.checker-drop[data-over] .checker-over{display:inline;color:var(--ln-accent)}
.checker-drop.ln-compact{min-height:0;cursor:default}
.checker-drop.ln-compact .ln-drop-meta{display:none}
.checker-drop.ln-compact .ln-btn{margin-block:0}
@media (max-width:640px){.checker-drop{--ln-drop-pad:var(--ln-xl);min-height:0}}

.checker-notice{margin:var(--ln-md) 0 0}

/* Paste and limits fold away under the zone as quiet disclosures. */
.checker-tools{display:flex;flex-wrap:wrap;gap:0 var(--ln-xl);margin-block-start:var(--ln-xs)}
.checker-more{display:block}
.checker-more[open]{flex-basis:100%}
.checker-more-body{display:grid;gap:var(--ln-sm);max-width:44rem;padding-block:var(--ln-xs) var(--ln-md)}
.checker-more-body>p{margin:0}
.checker-text{min-height:9rem;font:400 var(--ln-fs-callout)/1.5 var(--ln-font-mono);text-align:left}
.checker-row{display:flex;flex-wrap:wrap;gap:var(--ln-sm)}
.checker-limit-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(13rem,1fr));gap:var(--ln-md)}
.checker-field .ln-input{max-width:8rem}
.checker-field .ln-field-hint{font-size:var(--ln-fs-caption)}

/* Results. */
.checker-results{margin-block-start:var(--ln-xl);scroll-margin-block-start:var(--ln-lg)}
.checker-results-title{margin:0 0 var(--ln-md);font-size:var(--ln-fs-title);font-weight:600}
.checker-results-title:focus{outline:none}
.checker-banner{align-items:flex-start}
.checker-banner-title{display:block;font-size:var(--ln-fs-body)}
.checker-banner-detail{margin:var(--ln-xs) 0 0;max-width:68ch}
.checker-facts{display:grid;grid-template-columns:repeat(auto-fit,minmax(9.5rem,1fr));gap:var(--ln-md) var(--ln-lg);margin:var(--ln-lg) 0 0;padding:0}
.checker-facts>div{min-width:0}
.checker-facts>.checker-fact-wide{grid-column:span 2}
.checker-facts bdi{white-space:nowrap}
.checker-facts dt{color:var(--ln-ink-quiet);font-size:var(--ln-fs-caption)}
.checker-facts dd{margin:2px 0 0;font-weight:600;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}
.checker-actions{display:flex;flex-wrap:wrap;gap:var(--ln-sm);margin-block:var(--ln-lg) var(--ln-xs)}
.checker-report-note{margin:0;max-width:60ch}

.checker-section{margin-block-start:var(--ln-xl)}
.checker-section-title{display:flex;align-items:center;gap:var(--ln-sm);margin:0;font-size:var(--ln-fs-headline);font-weight:600}
.checker-section-intro{margin:var(--ln-xs) 0 var(--ln-sm);max-width:62ch}
.checker-group{border-block-start:1px solid var(--ln-hairline)}
.checker-section>.checker-group:last-child{border-block-end:1px solid var(--ln-hairline)}
.checker-group-summary{gap:var(--ln-sm)}
.checker-group-title{min-width:0;text-wrap:balance}
.checker-explain{max-width:68ch;margin:0 0 var(--ln-sm)}
.checker-table{font-size:var(--ln-fs-callout)}
.checker-table th,.checker-table td{padding:var(--ln-sm)}
.checker-table th{text-transform:none;letter-spacing:0;font-size:var(--ln-fs-caption)}
/* Same column widths in every group. */
@media (min-width:641px){.checker-table{table-layout:fixed}.checker-table th:nth-child(1){width:6rem}.checker-table th:nth-child(2){width:9.5rem}}
/* Phone: one block per finding, each cell labelled. Lantern's ln-stack-sm is not used because its class
   name also matches the generic flex-column stack utility, which breaks a table on wide screens. */
@media (max-width:640px){
.checker-table,.checker-table tbody,.checker-table tr{display:block}
.checker-table thead{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%)}
.checker-table tr{padding-block:var(--ln-sm);border-block-end:1px solid var(--ln-hairline)}
.checker-table tbody tr:last-child{border-block-end:0}
.checker-table td{display:grid;grid-template-columns:minmax(5em,30%) minmax(0,1fr);gap:var(--ln-md);padding:var(--ln-xs) var(--ln-sm);border:0}
.checker-table td::before{content:attr(data-label);color:var(--ln-ink-quiet);font-size:var(--ln-fs-caption);font-weight:600}
}
.checker-cue{white-space:nowrap;font-weight:600;font-variant-numeric:tabular-nums}
.checker-line{display:block;color:var(--ln-ink-quiet);font-size:var(--ln-fs-caption);font-weight:400}
.checker-time{white-space:nowrap;font-family:var(--ln-font-mono);font-size:var(--ln-fs-caption);font-variant-numeric:tabular-nums}
.checker-raw{display:block;width:fit-content;max-width:100%;margin-block-start:2px;color:var(--ln-ink-quiet);font:400 var(--ln-fs-caption)/1.4 var(--ln-font-mono);overflow-wrap:anywhere;text-align:start}
.checker-shown{margin:var(--ln-xs) 0 0}
.checker-show-more{margin-block-end:var(--ln-sm)}
@media (max-width:640px){.checker-actions .ln-btn{flex:1 1 100%}}

/* The explainer under the tool. */
.checker-article{max-width:70ch}
.checker-article h2{margin-block-start:var(--ln-xxl)}
.checker-article h3{margin-block:var(--ln-xl) var(--ln-sm);font-size:var(--ln-fs-headline);font-weight:600}
.checker-article ul{margin-block:var(--ln-md) var(--ln-lg);padding-inline-start:1.35em}
.checker-article li+li{margin-block-start:var(--ln-sm)}
.checker-term>summary{text-wrap:balance}
.checker-term>p{margin:0 0 var(--ln-md);color:var(--ln-ink-secondary);line-height:1.55}
.checker-pointer{margin-block-start:var(--ln-xl)}
.checker-pointer a{color:var(--ln-accent);text-decoration:underline;text-underline-offset:.2em}

.wer-row[data-rank="0"]{--ln-meter:0.1533}
.wer-row[data-rank="1"]{--ln-meter:0.1667}
.wer-row[data-rank="2"]{--ln-meter:0.2100}
.wer-row[data-rank="3"]{--ln-meter:0.2467}
.wer-row[data-rank="4"]{--ln-meter:0.2467}
.wer-row[data-rank="5"]{--ln-meter:0.5667}
.wer-row[data-rank="6"]{--ln-meter:0.8367}
