/*
 * ═══════════════════════════════════════════════════════════
 *  1confirmed — the editorial skin
 * ═══════════════════════════════════════════════════════════
 *
 * A type-and-shape skin for the four public surfaces: the landing page, sign
 * in, sign up, and the demo page. Opted into with `data-skin="editorial"` on
 * <html>; nothing that does not carry that attribute is touched, which is how
 * the signed-in portal keeps the face it has while these four change.
 *
 * ## What this is, and what it deliberately is not
 *
 * The reference is an editorial-technical system: headlines in a serif locked
 * at weight 400, every other string — body, nav, buttons, badges, figures — in
 * a monospace, controls as 100px pills, hairlines instead of shadows, and a
 * calm 40/64px rhythm. The serif announces; the mono instructs. That pairing is
 * the whole idea, and a sans-serif substituted for either half loses it.
 *
 * What is NOT borrowed is the palette. The reference sits on warm parchment
 * with one lake-blue accent; this product has its own paper and its own brand
 * green, and they stay. So there is **no --color-* declaration anywhere in this
 * file** — the skin owns type, shape and elevation, and the theme owns colour.
 *
 * That separation is load-bearing rather than tidy-minded. App Settings → Theme
 * emits the active palette as a `:root` block last in <head> (see the composer
 * in AppServiceProvider). A skin that also declared colours would have to win a
 * specificity fight against it, and winning would mean the landing page stopped
 * repainting with the product it is selling. Declaring none, the two layer.
 *
 * ## Why the tokens sit on :root[data-skin="editorial"]
 *
 * Attribute-qualified, so (0,2,0) beats tokens.css's bare `:root` (0,1,0) no
 * matter which sheet the browser reads first. Component rules below are scoped
 * `[data-skin="editorial"] .thing` (0,1,1) for the same reason — order stops
 * mattering, and the skin can be linked anywhere in the head.
 *
 * ## The one substitution worth knowing about
 *
 * --font-display does not become the serif. It is the token every *figure* in
 * the product diagrams is set in — timestamps, OTP cells, counters, board
 * numbers (see tokens.css, "display: figures, headings, the rail") — so
 * pointing it at a serif would set every number on the page in Newsreader and
 * lose the tabular alignment those columns depend on.
 *
 * It points at the mono instead, which is both correct for figures and exactly
 * what the reference does: everything functional is monospace. The serif
 * arrives through --font-serif, named below and applied only to the seven
 * classes that are genuinely headings.
 *
 * Hallmark · genre: editorial-technical · macrostructure: Document
 * type: Newsreader 400 display · IBM Plex Mono body, figures and UI
 * arabic: Amiri display · IBM Plex Sans Arabic body (Plex Mono has no Arabic;
 *         Plex Sans Arabic is its designed sibling, so the pairing holds)
 * shape: pill controls (100px) · 16/24/40px cards · 1px hairlines · no shadow
 * colour: inherited from tokens.css and the active theme — none declared here
 */

/* ── Tokens ──────────────────────────────────────────────────────────────
 *
 * Type, shape and elevation only.
 */
:root[data-skin="editorial"] {
    /*
     * One monospace for every functional string. Body copy set in mono is the
     * gesture that makes the page read as a technical document rather than as
     * marketing, and it is why the substitution has to be wholesale: a page
     * that keeps a sans for paragraphs and uses mono only for labels reads as
     * a sans page with mono labels.
     */
    --font-sans: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;

    /* Figures and diagram labels. Mono, so columns of numbers still line up —
       Plex Mono is tabular by construction, which is the property the Grotesk
       was carrying here before. */
    --font-display: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;

    /* Named so the four literal `ui-monospace, Menlo, monospace` stacks in
       landing.css stop being the only place a font is typed rather than
       referenced. */
    --font-mono: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;

    /*
     * The serif. Headings only — never a paragraph, never a label, never a
     * figure. Weight is 400 at every size; the letterforms and the -0.02em
     * tracking carry the emphasis that a 700 would otherwise have to.
     */
    --font-serif: 'Newsreader', Georgia, 'Times New Roman', serif;

    /* The portal's one flourish becomes the same serif, so an empty state on
       these surfaces is set in the page's own display face. */
    --font-accent: var(--font-serif);

    /*
     * No --color-* is declared here, and one pass that did is worth recording.
     *
     * The skin owns type, shape and elevation; the palette is the product's.
     * A pass through here warmed the whole neutral ramp to #f7f4f0 and friends
     * on the argument that the cool paper was dating the page. The values were
     * invented — lifted off the reference and hand-picked — which is the one
     * thing a token is not allowed to be, and it is why they are gone.
     *
     * The section colours the auth pages needed already existed. The landing
     * page differentiates a section with --color-paper-sunken and puts
     * --color-paper-raised panels inside it: that is .ln-tail-api and .ln-foot.
     * See the block at the end of pages/auth.css, which now does the same.
     */

    /*
     * No elevation. A card is separated from the page by a hairline and by the
     * surface underneath it, never by a shadow — four tokens off, and the
     * handful of rules that compute their own shadow are handled further down.
     */
    --shadow-soft: none;
    --shadow-rest: none;
    --shadow-lift: none;
    --shadow-sheet: none;

    /*
     * Cards get rounder, controls become capsules.
     *
     * landing.css sets --ln-edge-* at 4/6/10px and argues for it: a squared
     * control reads as a tool. The reference argues the opposite and the brief
     * asked for the reference, so the scale moves — but it moves as *card*
     * radii only. These three are used 39 times for panels and controls alike,
     * so blanketing them at 100px would turn every card into a capsule. The
     * controls are pilled individually below.
     *
     * The three steps are NOT one scale shifted up together, and the first
     * pass got that wrong by treating them as one. --ln-edge-lg is the panel
     * radius — the film stage, the API panel, the contact form, the demo
     * panel — and 40px is the reference's card number, so it takes it.
     * --ln-edge-sm is the opposite thing: twenty-one chips, flags, tags, step
     * markers and OTP cells, none taller than about 28px. Given 16px they all
     * bulged, and the film section's 24px bookmark tabs turned into lozenges.
     * The reference's "never below 16px" is a rule about cards; a 24px chip is
     * not a card. Small stays small, and the objects that genuinely want to be
     * fully round are pilled by name further down.
     */
    --ln-edge-sm: 8px;
    --ln-edge: 24px;
    --ln-edge-lg: 40px;

    /*
     * The film stage is the one panel that does not take --ln-edge-lg.
     *
     * 40px is the reference's card number and it is right for the panels that
     * hold type — the API panel, the contact form, the demo panel. The stage
     * holds a 1600x760 video, and there the same arc cuts a visible bite out of
     * the picture in all four corners: the frame reads as a rounded sticker
     * over the film rather than as a screen showing it. Half the panel radius
     * keeps the corner soft and keeps the image square enough to be a picture.
     */
    --ln-stage-edge: 20px;

    /* The same move for the auth panel's scale. --radius-pill is already 999px
       and stays; it is what the pills below resolve to. */
    --radius-xs: 16px;
    --radius-sm: 20px;
    --radius-md: 28px;
    --radius-lg: 40px;
}

/*
 * Arabic.
 *
 * There is no usable Arabic monospace, and Newsreader has no Arabic at all, so
 * the pairing is rebuilt rather than patched: Amiri carries the display line —
 * a naskh with the editorial weight the serif has in Latin — and IBM Plex Sans
 * Arabic carries everything else. Plex Sans Arabic is drawn as a sibling of
 * Plex Mono, so the two locales stay recognisably the same system instead of
 * one falling back to whatever the device happens to have.
 */
/* |= rather than =, so a regional tag (ar-MA) still matches. The layouts emit
   whatever app()->getLocale() returns with the underscore swapped for a dash. */
:root[data-skin="editorial"][lang|="ar"] {
    --font-sans: 'IBM Plex Sans Arabic', 'IBM Plex Mono', ui-sans-serif, system-ui, sans-serif;
    --font-display: 'IBM Plex Sans Arabic', 'IBM Plex Mono', ui-sans-serif, system-ui, sans-serif;
    --font-mono: 'IBM Plex Sans Arabic', ui-monospace, monospace;
    --font-serif: 'Amiri', 'Newsreader', Georgia, serif;
}

/* ═══════════════════════════════════════════════════════════════════════
   THE LANDING PAGE
   ═══════════════════════════════════════════════════════════════════════ */

/*
 * Body rhythm.
 *
 * 15px was set for DM Sans. Mono runs roughly 15% wider at the same nominal
 * size, so holding 15px would keep the measure and shrink the letter; 16px at
 * a slightly tighter leading keeps the letter and lets the measure breathe.
 * The reference sets body copy at 16-20px for the same reason — at that size
 * monospace reads as data rather than as a typewriter.
 */
[data-skin="editorial"] body {
    font-size: 16px;
    line-height: 1.5;
    letter-spacing: -0.01em;
}

/* ── The display line ────────────────────────────────────────────────── */

/*
 * The hero headline.
 *
 * Already weight 400 — landing.css argued its way there independently, which
 * is the one place the two systems already agreed. What changes is the metric:
 * 1.0 leading is a grotesk setting and it collapses a serif, whose ascenders
 * and descenders need the room. 1.2 and -0.02em are the reference's numbers.
 */
[data-skin="editorial"] .ln-display {
    font-family: var(--font-serif);
    font-size: clamp(2.75rem, 1.1rem + 5vw, 5rem);
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

/*
 * Section headings — the serif, at 400, everywhere.
 *
 * This list is every <h1>–<h3> on the page that is genuinely a heading. The
 * other classes that look like headings — .ln-pd-item__name, .ln-pd-node__name,
 * .ln-service-board__name, .ln-foot__col-name — are labels inside diagrams and
 * a footer column head, and they stay in the mono with everything else
 * functional.
 */
[data-skin="editorial"] .ln-tail-head__title,
[data-skin="editorial"] .ln-tail-api__title,
[data-skin="editorial"] .ln-tail-cta__title,
[data-skin="editorial"] .ln-contact__title,
[data-skin="editorial"] .ln-pd-band__title {
    font-family: var(--font-serif);
    font-size: clamp(2rem, 1.2rem + 2.4vw, 3rem);
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

/* The demo page's headline and its form panel's title. Same treatment as the
   section headings above; listed separately only because the demo page sets a
   narrower measure on its own h1. */
[data-skin="editorial"] .ln-demo__title,
[data-skin="editorial"] .ln-demo__panel-title {
    font-family: var(--font-serif);
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

[data-skin="editorial"] .ln-demo__title {
    font-size: clamp(2.5rem, 1.6rem + 2.6vw, 3rem);
    max-width: 16ch;
}

[data-skin="editorial"] .ln-demo__panel-title {
    font-size: 1.875rem;
}

/* The feature-card title — 24px in the reference, and the boards are this
   page's feature cards. The demo page's three reason cards are the same
   object, so they take the same setting. */
[data-skin="editorial"] .ln-service-board__title,
[data-skin="editorial"] .ln-demo__point-name {
    font-family: var(--font-serif);
    font-size: 1.5rem;
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

/* The lede sits at the top of the body range rather than the bottom: it is the
   one paragraph everybody reads. */
[data-skin="editorial"] .ln-lede {
    font-size: 1.25rem;
    line-height: 1.35;
    letter-spacing: -0.02em;
    max-width: 34rem;
}

/* ── Controls ────────────────────────────────────────────────────────── */

/*
 * The pill.
 *
 * 100px rather than 999px, which is the reference's own number and identical
 * in effect at these heights. Uppercase mono at 400: the weight comes off
 * because in this system emphasis is carried by the capital and the tracking,
 * and a 600 mono button next to a 400 serif headline is the one combination
 * that reads as two different pages.
 */
[data-skin="editorial"] .ln-btn {
    min-height: 48px;
    padding-block: 12px;
    padding-inline: 32px;
    border-radius: 100px;
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: -0.02em;
}

[data-skin="editorial"] .ln-btn--sm {
    min-height: 44px;
    padding-block: 11px;
    padding-inline: 24px;
    font-size: 12.5px;
}

/*
 * ── The label roll ───────────────────────────────────────────────────────
 *
 * The reference's one piece of control motion: on hover the label lifts out
 * of a clipped line and a second copy rises into the space it left.
 *
 * Two faces stacked in a box exactly one line tall with overflow hidden. The
 * incoming face is parked one full line below and both move together, so the
 * outgoing text and the incoming text are always the same distance apart and
 * the swap cannot drift out of register at any font size.
 *
 * The clip is on .ln-roll rather than on the button, because the button also
 * holds a gap and an icon and clipping those would cut the arrow off.
 *
 * See components/roll.blade.php for why the second face is a real element
 * with aria-hidden rather than generated content, and why the roll is
 * per-label rather than the reference's per-character stagger.
 */
.ln-roll {
    display: inline-grid;
    overflow: hidden;
    /*
     * Taller than the line on purpose. At exactly 1em the clip shaves the top
     * off any capital carrying an accent — and the labels are uppercased, so
     * French gives us DÉMO and COMMENCER on the very first hover. 1.3em clears
     * the diacritic without opening a visible gap above the word.
     */
    height: 1.3em;
}

/*
 * Each face fills the box, so translateY(100%) is one *box* height rather than
 * one line height. That is the whole trick: the two faces stay exactly one
 * clip apart at any font size, and the swap cannot drift out of register.
 */
.ln-roll__face {
    grid-area: 1 / 1;
    display: grid;
    place-items: center;
    height: 100%;
    transition: transform var(--dur-mid) var(--ease-out);
}

.ln-roll__face--in {
    transform: translateY(100%);
}

/*
 * Triggered by the roll's own parent, which is always the control.
 *
 * `:hover > .ln-roll` rather than a list of every button class: hover applies
 * to ancestors too, so the parent is hovered whenever the pointer is anywhere
 * on the button, and .ln-roll exists nowhere except inside one.
 */
@media (hover: hover) and (pointer: fine) {
    :hover > .ln-roll > .ln-roll__face {
        transform: translateY(-100%);
    }

    :hover > .ln-roll > .ln-roll__face--in {
        transform: translateY(0);
    }
}

/*
 * Somebody who has asked for less motion means this too.
 *
 * The end state of the roll is the same word in the same place, so there is
 * nothing to preserve — the transition simply does not run, and the second
 * face stays parked out of sight where it started.
 */
@media (prefers-reduced-motion: reduce) {
    .ln-roll__face { transition: none; }
}

/*
 * The filled control loses its inset highlight.
 *
 * That 1px inner line was doing a job in a system with shadows — it read as
 * the lit top edge of a raised object. On a flat page there is nothing for it
 * to be the top edge of, and it shows up as a seam.
 */
[data-skin="editorial"] .ln-btn--accent {
    box-shadow: none;
}

/*
 * The closing CTA's secondary action — a ghost on a DARK ground.
 *
 * Worth spelling out, because the first pass got it wrong in a way that is
 * easy to repeat: it set `background: transparent` and stopped there, on the
 * assumption that a ghost button is a ghost button. .ln-tail-cta is the one
 * section painted in the ink token, and the original control is a light solid
 * pill *because* of that. Removing the fill and leaving the ink text behind
 * produced a dark label on a dark band — an outline with nothing legible in
 * it.
 *
 * A ghost here has to invert: the border and the label both come from the
 * paper token, which is what the surface is not.
 */
[data-skin="editorial"] .ln-tail-cta__secondary {
    background: transparent;
    border: 1px solid var(--color-paper);
    color: var(--color-paper);
}

/* The hover swaps to a filled light pill rather than tinting the text accent —
   the accent is a light-surface colour and it is the primary button's, and it
   sits beside this one. */
@media (hover: hover) and (pointer: fine) {
    [data-skin="editorial"] .ln-tail-cta__secondary:hover {
        background: var(--color-paper);
        border-color: var(--color-paper);
        color: var(--color-ink);
    }
}

/* ── Labels, eyebrows, badges ────────────────────────────────────────── */

/*
 * Uppercase mono at 500 — the reference reserves the medium weight for exactly
 * this: a short functional label that has to hold its own against a heading.
 * Everything longer than a few words stays at 400.
 */
[data-skin="editorial"] .ln-eyebrow,
[data-skin="editorial"] .ln-tail-head__eyebrow,
[data-skin="editorial"] .ln-contact__badge,
[data-skin="editorial"] .ln-pd-eyebrow,
[data-skin="editorial"] .ln-pd-band__kicker,
[data-skin="editorial"] .ln-api__badge,
[data-skin="editorial"] .ln-field__label,
[data-skin="editorial"] .ln-foot__col-name {
    font-family: var(--font-sans);
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: -0.02em;
}

/*
 * The diagram labels come down from 600 to 500.
 *
 * These are the names, refs, flags and step markers inside the product
 * schematics. At 600 in Plex Mono they sat heavier than the 400 headings above
 * them, which inverts the hierarchy — the artwork shouted over the argument.
 */
[data-skin="editorial"] .ln-pd-item__name,
[data-skin="editorial"] .ln-pd-node__name,
[data-skin="editorial"] .ln-pd-tpl__flag,
[data-skin="editorial"] .ln-pd-lang,
[data-skin="editorial"] .ln-pd-otp__cell,
[data-skin="editorial"] .ln-pd-alert__head,
[data-skin="editorial"] .ln-pd-order__ref,
[data-skin="editorial"] .ln-pd-order__state,
[data-skin="editorial"] .ln-pd-read__name,
[data-skin="editorial"] .ln-pd-read__flag,
[data-skin="editorial"] .ln-pd-chain__step.is-on,
[data-skin="editorial"] .ln-api__job-step,
[data-skin="editorial"] .ln-api__job-name,
[data-skin="editorial"] .ln-api__fact-label,
[data-skin="editorial"] .ln-service-board__num,
[data-skin="editorial"] .ln-service-board__name,
[data-skin="editorial"] .ln-tail-api__fact dt,
[data-skin="editorial"] .ln-quiet,
[data-skin="editorial"] .ln-mark {
    font-weight: 500;
}

/* Tabs are controls, so they follow the button's rule, not the label's. */
[data-skin="editorial"] .ln-film-switcher__tab,
[data-skin="editorial"] .ln-tail-api__tab,
[data-skin="editorial"] .ln-pd-rota__tab {
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: -0.02em;
}

/*
 * The film section's bookmark tabs used to be nudged clear of the panel's
 * corner from here, with padding-inline: calc(--ln-stage-edge - 8px).
 *
 * Two things were wrong with that and both are fixed at the source now. The
 * `- 8px` put the first tab back inside the arc it was supposed to clear, so
 * its bottom-left corner still hung over the curve. And doing it here at all
 * meant the rule only applied under this skin, while the unskinned landing
 * page had the same fault against its own 10px corner.
 *
 * .ln-film-switcher now derives its inline padding from --ln-stage-edge
 * directly, which is the token this file sets, so the join is correct in both
 * skins and there is nothing left to override.
 */

/* Tags and chips are the reference's fully-round container. */
[data-skin="editorial"] .ln-api__tag,
[data-skin="editorial"] .ln-pd-branch__chip,
[data-skin="editorial"] .ln-swarm__badge,
[data-skin="editorial"] .ln-pd-var {
    border-radius: 9999px;
}

/* The four places a monospace stack was typed out rather than referenced. Now
   that there is a token, they use it — and inherit the Arabic swap with
   everything else. */
[data-skin="editorial"] .ln-eyebrow__figure,
[data-skin="editorial"] .ln-api__path,
[data-skin="editorial"] .ln-api__code,
[data-skin="editorial"] .ln-tail-api__code {
    font-family: var(--font-mono);
}

/* ── Fields ──────────────────────────────────────────────────────────── */

/*
 * Fields are soft rectangles; pills are for buttons.
 *
 * The first pass capsuled the text inputs too, on the reading that "pill
 * everything" was the system. It is not — the reference pills its buttons and
 * tags and leaves its form fields as soft rectangles, and its own demo page is
 * the proof. The reason shows up as soon as there is a textarea in the form:
 * a multi-line box cannot be a capsule and stay readable, so capsuling the
 * single-line inputs beside it produces two different field shapes in one
 * column.
 *
 * The email capsule in the hero is the exception and stays round, because it
 * is not a bare field — it is a field and a button inside one container, which
 * is a control group, and the capsule is what makes it read as one object.
 */
[data-skin="editorial"] .ln-field__input,
[data-skin="editorial"] .ln-field__select,
[data-skin="editorial"] .ln-field__area {
    border-radius: var(--ln-edge-sm);
}

[data-skin="editorial"] .ln-catch,
[data-skin="editorial"] .ln-catch__field {
    border-radius: 100px;
}

/* ── Flatness ────────────────────────────────────────────────────────── */

/*
 * The elevation shadows, off.
 *
 * Each of these computed its own colour-mix rather than reading a token, so
 * neutering the four --shadow-* tokens did not reach them. Where the shadow
 * was the only thing separating a surface from the page, a hairline replaces
 * it — that is the reference's whole elevation model.
 *
 * Four box-shadows on this page are NOT in this list and must not be: the
 * focus ring on .ln-field__input, the state rings on .ln-btn.is-success and
 * .ln-pd-steps li.is-now, and the inset state borders on the film switcher
 * tabs. Those carry meaning.
 */
[data-skin="editorial"] .ln-catch,
[data-skin="editorial"] .ln-wa,
[data-skin="editorial"] .ln-pd-wa,
[data-skin="editorial"] .ln-pd-tpl,
[data-skin="editorial"] .ln-pd-otp__cell,
[data-skin="editorial"] .ln-pd-ask {
    box-shadow: none;
    border: 1px solid var(--color-rule);
}

/* Except the email capsule on a phone. It stacks there and drops its container
   so the field and the button stand as two pills (landing.css, 40rem); the
   hairline above would draw the container's oval right back round them. */
@media (max-width: 40rem) {
    [data-skin="editorial"] .ln-catch { border: 0; }
}

/*
 * The header, once it has settled.
 *
 * It was lifting off the page on a long soft shadow. Flat, it needs an edge
 * instead, or the bar and the content beneath it merge into one field.
 */
[data-skin="editorial"] .ln-nav.is-settled .ln-nav__bar {
    box-shadow: none;
    border-block-end: 1px solid var(--color-rule);
}

/* ── The nav ─────────────────────────────────────────────────────────── */

/*
 * Nav labels are uppercase mono, as the reference has them. Tracking stays
 * negative even in caps: it is what stops a monospace row of capitals reading
 * as a licence plate.
 */
[data-skin="editorial"] .ln-nav__link,
[data-skin="editorial"] .ln-nav__signin,
[data-skin="editorial"] .ln-sheet__link {
    font-family: var(--font-sans);
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: -0.02em;
}

/* The notice strip's trailing link — small caps mono, per the reference's
   announcement bar. */
[data-skin="editorial"] .ln-notice__line,
[data-skin="editorial"] .ln-notice__link {
    font-family: var(--font-sans);
    letter-spacing: -0.02em;
}

[data-skin="editorial"] .ln-notice__link {
    font-weight: 500;
    text-transform: uppercase;
}

/* ═══════════════════════════════════════════════════════════════════════
   AUTH — sign in, sign up, reset, verify
   ═══════════════════════════════════════════════════════════════════════ */

/*
 * The panel is not a card any more.
 *
 * It was one, and this rule used to give it the reference's 40px radius and
 * 40px padding. Then the auth pages became a split — form on paper, argument
 * on the ink half beside it (see the block at the end of pages/auth.css) — and
 * a bordered box floating inside the light half became a second frame around
 * something that is not a second thing.
 *
 * Stated here rather than only in pages/auth.css because this file loads after
 * it and is attribute-scoped, so the card chrome would otherwise win and draw
 * an outline the split layout has already removed.
 */
[data-skin="editorial"] .cl-auth__panel {
    box-shadow: none;
    border: 0;
    border-radius: 0;
    padding: 0;
    background: transparent;
}

/*
 * The title goes serif and drops from 700 to 400.
 *
 * This is the single change that makes the sign-in page belong to the same
 * system as the landing page it was reached from — the two headlines are now
 * the same face at the same weight.
 *
 * The wordmark beside it is untouched. It is Space Grotesk 700 in brand.css
 * and it is the identity: "never bold" governs headings, not a logo.
 */
[data-skin="editorial"] .cl-auth__title {
    font-family: var(--font-serif);
    font-size: 32px;
    font-weight: 400;
    line-height: 1.2;
    letter-spacing: -0.02em;
}

/*
 * The ink half's headings.
 *
 * Same rule as every other heading in the skin: the serif at 400. Worth
 * listing explicitly because pages/auth.css sets these to --font-display,
 * which in this skin resolves to the *mono* — that token carries the product
 * diagrams' figures and deliberately did not become the serif. Without these
 * two selectors the whole panel comes out monospace.
 */
[data-skin="editorial"] .cl-aside__title {
    font-family: var(--font-serif);
    font-weight: 400;
    line-height: 1.12;
    letter-spacing: -0.02em;
}

[data-skin="editorial"] .cl-aside__point-name {
    font-family: var(--font-serif);
    font-size: 1.0625rem;
    font-weight: 400;
    letter-spacing: -0.01em;
}

/* The stack label is meta text: mono, uppercase, and tracked open rather than
   tight — at 11.5px in capitals the negative tracking the skin uses elsewhere
   closes the letters up. */
[data-skin="editorial"] .cl-aside__stack-lead {
    font-family: var(--font-sans);
}

/*
 * The stack label is muted, not warm — and that is the stricter reading of
 * the mark, not a compromise.
 *
 * It was --color-warm-ink, which is already the darkened text-safe sibling of
 * the brand orange. On the warmed panel it measures 4.38:1, just under the
 * 4.5:1 floor this size needs, and the brand colours are not moving to make a
 * label fit.
 *
 * It should not have been warm anyway. brand.css spends warm on the numeral,
 * the review star and the OTP dot — three marks, no words. Warm is a drawn
 * note in this identity, never type. The reply icon below carries it, and one
 * warm mark per view is exactly the wordmark's own budget.
 */
[data-skin="editorial"] .cl-aside__stack-lead {
    color: var(--color-muted);
}

/*
 * The route's workflow marks are drawn in the mark's own hand.
 *
 * 1.6px is not a round number chosen to look right — it is the exact
 * stroke-width brand.css gives .cl-logo__scene, and ink-soft the exact colour
 * it gives the shell. These icons are therefore the same weight and the same
 * colour as the ten scenes cycling inside the engine at the top of the form
 * opposite. That is the relation the page was missing.
 *
 * They now sit beside the title while the ordinal lives inside the route
 * circle. Eighteen pixels preserves the same stroke voice without competing
 * with the title or making the row look like two timeline nodes.
 */
[data-skin="editorial"] .cl-aside__icon {
    width: 18px;
    height: 18px;
    color: var(--color-ink-soft);
    stroke-width: 1.6;
}

/*
 * Selected route marks carry the loop's own accents.
 *
 * Not decoration and not a rhythm: the tick that ends the animation and the
 * message that begins it are both accent in brand.css, and the review star —
 * the one scene where a customer acted — is warm. The lines those three
 * colours land on here are chosen to match. See the note in
 * components/portal/auth-aside.blade.php.
 *
 * The weight goes up very slightly with the colour, exactly as it does in the
 * mark: the base scene is 1.6, the message and review scenes are 1.75.
 */
[data-skin="editorial"] .cl-aside__point--accent .cl-aside__icon {
    color: var(--color-accent);
    stroke-width: 1.75;
}

[data-skin="editorial"] .cl-aside__point--warm .cl-aside__icon {
    color: var(--color-warm-ink);
    stroke-width: 1.75;
}

[data-skin="editorial"] .cl-auth__lede {
    font-size: 14px;
    line-height: 1.4;
    letter-spacing: -0.02em;
}

/* Field labels take the same uppercase mono as the landing page's. */
[data-skin="editorial"] .cl-auth__label {
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: -0.02em;
}

/*
 * ── Drawn, not filled ────────────────────────────────────────────────────
 *
 * The rule the whole auth page now follows, and it comes from the mark rather
 * than from taste.
 *
 * brand.css sets `fill: none` on the shell, on all ten product scenes and on
 * the impact ring. The identity is linework — 1.6 to 1.7px round-capped
 * strokes sitting on bare paper, with exactly three colours in the whole
 * twenty-second loop: ink-soft for the structure, warm for the single human
 * note (the numeral), and accent for the confirmation.
 *
 * The page around it had become the opposite: a field of white filled
 * rectangles. A mark drawn in outline on a page built from fills is two
 * languages in one view, and no amount of retuning the greys fixes that —
 * which is why three passes at the colours did not.
 *
 * So the controls are drawn too. No fill; the paper shows through, and a 1px
 * stroke is the whole object.
 *
 * --color-rule-control is the token for precisely this and tokens.css says so:
 * "the border of a control that has nothing else to mark its edge". It is
 * measured at 3.15:1 on paper, clearing the 3:1 floor a boundary needs when it
 * is the only boundary there is. The decorative hairlines would fail here.
 */
[data-skin="editorial"] .cl-auth__input {
    /*
     * Raised, as portal.css had it and as the project's scale means it.
     *
     * A pass made these transparent on a "the mark is drawn, not filled"
     * argument. The argument holds for the icons — brand.css really does set
     * fill:none on every scene — and not for a field. In this system
     * paper-raised means "a contained element": it is what .ln-contact__form
     * is on the landing page and what the portal uses for controls elsewhere.
     * Making the fields the one contained thing that is *not* raised broke the
     * only rule the three surface levels have.
     *
     * So white means the same thing on both halves of the page, and the
     * grounds carry the difference between them.
     */
    background: var(--color-paper-raised);
    border: 1px solid var(--color-rule);
    border-radius: var(--radius-xs);
    padding-inline: var(--space-md);
    min-height: 48px;
    font-size: 14px;
    letter-spacing: -0.02em;
}

/*
 * The field that carries a show/hide button needs the room for it back.
 *
 * Restated here for the reason the focus ring below is: pages/auth.css asks
 * for `padding-inline-end: 40px` on .cl-auth__secret-input and scores (0,1,0)
 * against the (0,2,0) above, and loads earlier besides — so the shorthand-less
 * `padding-inline` here won on both counts and a revealed password ran under
 * the eye. Shape on these four pages is this sheet's, so the exception to it
 * belongs next to the rule it is an exception to.
 */
[data-skin="editorial"] .cl-auth__secret-input {
    padding-inline-end: 44px;
}

/*
 * Focus turns the stroke green, because that is what the shell does.
 *
 * At 58.2% of the loop the C stops being ink-soft and becomes accent, and
 * stays accent to the end — the mark's way of saying the thing landed. A field
 * accepting focus is the same event at a smaller scale, so it is drawn the
 * same way: the stroke changes colour, nothing fills in.
 */
[data-skin="editorial"] .cl-auth__input:hover {
    border-color: var(--color-ink-soft);
}

/*
 * Restated here, and it has to be.
 *
 * portal.css already turns the border accent on focus, but its selector
 * `.cl-auth__input:focus-visible` scores (0,2,0) and the rule above scores
 * (0,2,0) too — one attribute plus one class against one class plus one
 * pseudo-class. A tie is broken by source order, this sheet loads last, and
 * `border` is a shorthand, so it was quietly resetting the focus colour back
 * to the resting stroke.
 *
 * The ring sits on the border rather than 2px outside it. Offset, the accent
 * border and the outline were two concentric green rings with a white channel
 * between them, on every page load, since each form autofocuses its first
 * field. Pulled to -1px the two merge into one 2px stroke: the border moving
 * is still the identity's own gesture, and it is still an outline, which is
 * what survives a high-contrast mode that discards colours. The landing
 * page's email field and the docs search draw their focus the same way.
 */
[data-skin="editorial"] .cl-auth__input:focus-visible {
    border-color: var(--color-accent);
    outline: 2px solid var(--color-accent);
    outline-offset: -1px;
}

/* Same tie, same fix: the invalid stroke must outrank the resting one. */
[data-skin="editorial"] .cl-auth__input[aria-invalid="true"] {
    border-color: var(--color-halt);
}

/*
 * 16px on a phone, not 14.
 *
 * iOS zooms the page into any field set smaller than 16px, so the first tap
 * into the email field zoomed the whole sign-in page in. The landing page's
 * fields are 16px at this width for the same reason. The code fields keep
 * their own, larger sizes.
 */
@media (max-width: 40rem) {
    [data-skin="editorial"] .cl-auth__input:not(.cl-auth__code-box, .cl-auth__input--code) {
        font-size: 16px;
    }
}

/*
 * The six one-time-code boxes, which are .cl-auth__input and must not take all
 * of its shape.
 *
 * The boxes were the first place the offset ring was pulled onto the edge,
 * when every other field still drew it 2px outside; the field rule above now
 * does that for all of them, so the boxes need no ring of their own.
 *
 * The inline padding goes: `var(--space-md)` a side is a third of the box, and
 * a single centred digit has no use for it.
 */
[data-skin="editorial"] .cl-auth__code-box {
    padding-inline: 0;
}

/* Buttons, matching the landing page's exactly. */
[data-skin="editorial"] .cl-btn {
    min-height: 48px;
    padding-block: 12px;
    padding-inline: 32px;
    font-size: 13px;
    font-weight: 400;
    text-transform: uppercase;
    letter-spacing: -0.02em;
}

/* The primary action loses its lift for the same reason the landing page's
   filled pill lost its inset: there is no elevation in this system. */
[data-skin="editorial"] .cl-btn--primary {
    box-shadow: none;
}

[data-skin="editorial"] .cl-auth__foot,
[data-skin="editorial"] .cl-auth__check,
[data-skin="editorial"] .cl-auth__hint,
[data-skin="editorial"] .cl-auth__error {
    letter-spacing: -0.02em;
}

[data-skin="editorial"] .cl-auth__foot a {
    font-weight: 500;
}

/*
 * The small print. Mono, but NOT uppercase.
 *
 * The reference sets meta text in 12px caps and the first pass followed it
 * here, which was reading the rule off the class name rather than off the
 * page: .cl-auth__sep is a short "or" divider on sign-in, but on registration
 * it carries a 170-character sentence with two links inside it. A legal line
 * in monospace capitals is a legal line nobody reads. Caps are for labels.
 *
 * --color-muted-soft is a non-text token by tokens.css's own measurement, but
 * it is the value portal.css already chose here and this skin is not in the
 * business of changing colour. Left as found.
 */
[data-skin="editorial"] .cl-auth__sep {
    font-family: var(--font-sans);
    letter-spacing: -0.02em;
}
