/* ═══════════════════════════════════════════════════════════════════════════
 * DIURNAL DESIGN TOKENS — single source of truth (mirrors Theme/DiurnalTheme.cs).
 * A task app set on a soft lavender page: white rounded cards, deep violet ink,
 * and one acid-chartreuse highlighter standing in for attention. "Nocturne" is
 * the night edition. ThemeTests asserts this table stays in sync with the C#.
 *
 *   Token                Light       Dark
 *   bg (page)            #eeebfa     #211e2d
 *   surface (well)       #f9f8fd     #2a2638
 *   surface-raised       #ffffff     #302c3e
 *   line (rule)          #d8d2e6     #50485f
 *   ink                  #242034     #f3effb
 *   ink-muted            #5b566c     #c4bdd4
 *   ink-faint            #6b6579     #b1a8c4
 *   accent (MARKER)      #d4f03c     #d4f03c
 *   accent-hover         #c3e02b     #e2fc55
 *   accent-ink           #16140f     #14140f
 *   accent-text (olive)  #52620f     #c9e84a
 *   pri-high (vermilion) #bf2f19     #ff6b4a
 *   pri-medium (ochre)   #8a6205     #e0a93b
 *   pri-low (olive)      #52620f     #c9e84a
 *   pri-none (slate)     #7b748c     #7f7893
 *
 * ── TWO RULES ──────────────────────────────────────────────────────────────
 *  1. --q-accent is a FILL, never text. Chartreuse on paper is 1.11:1 as type.
 *     Lay --q-accent-ink on it (14.31:1); for a foreground in the marker family
 *     use --q-accent-text (the deep olive sibling, 5.11:1).
 *  2. Vermilion means late, and nothing else — it is the sheet's only alarm.
 *
 * Every foreground token clears WCAG AA against its own paper. Priority colors
 * are dots and edge bars, not type; pri-none is quietest at 3.79:1 / 3.22:1,
 * over the 3:1 that WCAG 1.4.11 sets for non-text UI components.
 *
 * The --q-* prefix is kept as an opaque token namespace: renaming it would touch
 * ~700 references for no functional gain. It does not imply the old Quarry palette.
 * ═══════════════════════════════════════════════════════════════════════════ */
:root {
    /* Light — lavender */
    --q-bg: #eeebfa;
    --q-surface: #f9f8fd;
    --q-surface-raised: #ffffff;
    --q-line: #d8d2e6;
    --q-ink: #242034;
    --q-ink-muted: #5b566c;
    --q-ink-faint: #6b6579;
    --q-accent: #d4f03c;
    --q-accent-hover: #c3e02b;
    --q-accent-ink: #16140f;
    --q-accent-text: #52620f;
    --pri-high: #bf2f19;
    --pri-medium: #8a6205;
    --pri-low: #52620f;
    --pri-none: #7b748c;

    /* Derived washes (auto-flip via var(--q-accent)) */
    --q-accent-soft: color-mix(in srgb, var(--q-accent) 12%, transparent);
    --q-accent-softer: color-mix(in srgb, var(--q-accent) 6%, transparent);

    /* A hairline one step softer than --q-line, for rules inside a block. */
    --q-line-soft: #e6e1f0;

    /* The lavender well: behind an active entry, a symbol, a step number or a date. */
    --q-well: #dfdaf2;
    --q-well-ink: #403450;

    /* Radii — soft corners throughout: fields and buttons, then cards, then the
       page's own panels. */
    --radius-xs: 4px;
    --radius-sm: 10px;
    --radius-md: 12px;
    --radius-lg: 20px;
    --radius-xl: 24px;
    --radius-full: 999px;

    /* Shadows */
    --q-shadow-1: 0 1px 2px rgba(36, 32, 52, 0.06);
    --q-shadow-2: 0 12px 32px rgba(36, 32, 52, 0.12);

    /* Atmosphere — a clean page: no grain, no letterpress. */
    --q-grain-opacity: 0;
    --q-grain-blend: multiply;
    --q-edge-light: rgba(255, 255, 255, 0);
    --q-press: none;
    /* The marker swipe: multiply on paper so ink reads through the highlighter. */
    --q-mark-blend: multiply;
    --q-mark-ink: inherit;

    /* Type */
    --q-font-display: "Fraunces", "Public Sans", Georgia, serif;
    --q-font-body: "Public Sans", system-ui, -apple-system, sans-serif;
    --q-font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;

    /* Newsprint tooth — one tileable fractal-noise texture, laid over backgrounds at low opacity */
    --q-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='q'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23q)'/%3E%3C/svg%3E");
}

/* ── State washes ─────────────────────────────────────────────────────────
 *
 * Three colours that are not a paper or an ink but recur on both: the wash a
 * control takes under the pointer, type for something switched off, and the
 * slate blue an informational note is set in. The hover wash is mixed from
 * --q-ink-muted, so it flips with the nocturne block below on its own; the
 * other two are restated there, because a disabled grey and a slate that read
 * on lavender are lost on the night sheet. */
:root {
    --q-hover: color-mix(in srgb, var(--q-ink-muted) 6%, transparent);
    --q-ink-disabled: rgba(0, 0, 0, 0.376);
    --q-info: #3c5a6e;
}

/* KEEP-IN-SYNC: diurnal-nocturne — app dark mode (DB-persisted toggle sets
 * .theme-dark on the broadsheet's root). Tokens live on :root so popovers and
 * dialogs in the top layer inherit them.
 *
 * [data-theme="dark"] on <html> is the same switch thrown one element earlier:
 * App.razor stamps it from the persisted preference so the night tokens are in
 * force while the <head> is still parsing, before any shell markup has arrived
 * to be matched by :has(). window.slate.setTheme keeps it true after a toggle.
 *
 * The marker cannot simply invert: multiply against a dark sheet swallows the
 * chartreuse entirely, so at night the swipe becomes a solid fill with dark type
 * laid on it (--q-mark-blend / --q-mark-ink). */
:root:has(.theme-dark),
:root[data-theme="dark"]:not(:has(.auth-page)),
:root[data-public-theme="dark"]:has(.auth-page) {
    --q-bg: #211e2d;
    --q-surface: #2a2638;
    --q-surface-raised: #302c3e;
    --q-line: #50485f;
    --q-line-soft: #3f394e;
    --q-ink: #f3effb;
    --q-ink-muted: #c4bdd4;
    --q-ink-faint: #b1a8c4;
    --q-accent: #d4f03c;
    --q-accent-hover: #e2fc55;
    --q-accent-ink: #14140f;
    --q-accent-text: #c9e84a;
    --pri-high: #ff6b4a;
    --pri-medium: #e0a93b;
    --pri-low: #c9e84a;
    --pri-none: #7f7893;
    --q-well: #3c3451;
    --q-well-ink: #f3effb;
    --q-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3);
    --q-shadow-2: 0 12px 32px rgba(0, 0, 0, 0.45);
    --q-grain-opacity: 0;
    --q-grain-blend: overlay;
    --q-edge-light: rgba(255, 255, 255, 0.05);
    --q-press: none;
    --q-mark-blend: normal;
    --q-mark-ink: #14140f;

    /* The two state colours that do not ride a --q-* token down. */
    --q-ink-disabled: rgba(255, 255, 255, 0.2);
    --q-info: #8fb4cc;
}

/* KEEP-IN-SYNC: diurnal-nocturne — static SSR auth pages render before the
 * interactive shell exists, so they follow the OS scheme instead of the
 * .theme-dark class. Must stay byte-for-byte equivalent to the block above;
 * ThemeTests compares the two token sets and fails on any drift. */
@media (prefers-color-scheme: dark) {
    :root:has(.auth-page):not([data-public-theme="light"]):not([data-public-theme="dark"]) {
        --q-bg: #211e2d;
        --q-surface: #2a2638;
        --q-surface-raised: #302c3e;
        --q-line: #50485f;
        --q-line-soft: #3f394e;
        --q-ink: #f3effb;
        --q-ink-muted: #c4bdd4;
        --q-ink-faint: #b1a8c4;
        --q-accent: #d4f03c;
        --q-accent-hover: #e2fc55;
        --q-accent-ink: #14140f;
        --q-accent-text: #c9e84a;
        --pri-high: #ff6b4a;
        --pri-medium: #e0a93b;
        --pri-low: #c9e84a;
        --pri-none: #7f7893;
        --q-well: #3c3451;
        --q-well-ink: #f3effb;
        --q-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3);
        --q-shadow-2: 0 12px 32px rgba(0, 0, 0, 0.45);
        --q-grain-opacity: 0;
        --q-grain-blend: overlay;
        --q-edge-light: rgba(255, 255, 255, 0.05);
        --q-press: none;
        --q-mark-blend: normal;
        --q-mark-ink: #14140f;

        /* The two state colours that do not ride a --q-* token down. */
        --q-ink-disabled: rgba(255, 255, 255, 0.2);
        --q-info: #8fb4cc;
    }
}

/* The paper is painted on the root element, not only on the sheet. A page load
 * streams the <head> well before the shell's markup arrives, and whatever the
 * browser paints in that window comes from here — with no background declared
 * it painted its own white canvas, which read as a flash on every refresh of
 * the night edition. color-scheme carries the same news to the scrollbars and
 * to the browser's own pre-paint canvas. */
html {
    -webkit-text-size-adjust: 100%;
    background: var(--q-bg);
    color-scheme: light;
}

:root:has(.theme-dark),
:root[data-theme="dark"]:not(:has(.auth-page)),
:root[data-public-theme="dark"]:has(.auth-page) {
    color-scheme: dark;
}

/* Public pages follow the OS only when no explicit browser choice is set. */
@media (prefers-color-scheme: dark) {
    :root:has(.auth-page):not([data-public-theme="light"]):not([data-public-theme="dark"]) {
        color-scheme: dark;
    }
}

html, body {
    font-family: var(--q-font-body);
    margin: 0;
    padding: 0;
    width: 100%;
    height: 100%;
}

body {
    overflow: hidden;
    touch-action: manipulation;
}

h1, h2, h3, h4, h5, h6 {
    font-family: var(--q-font-display);
    letter-spacing: -0.01em;
}

/* Links take the olive sibling, not the marker: chartreuse type on paper is 1.11:1. */
a, .btn-link {
    color: var(--q-accent-text);
}

/* ── Type scale ─────────────────────────────────────────────────────────────
 *
 * The app's own typography, replacing MudText. Sizes, weights, leading and
 * tracking are the values MudBlazor derived from the Typography block in
 * DiurnalTheme.cs, read back off the rendered page — so the swap moved nothing.
 *
 * Fraunces carries the headings and the two subtitles; Public Sans carries body
 * and caption. That split is the design's, not MudBlazor's, and it is why the
 * subtitles sit with the display face rather than the body face.
 *
 * Every one of these sets margin: 0 — MudText did too, and the surrounding
 * layouts were all built on the assumption that type brings no space with it. */
.q-h4, .q-h5, .q-h6, .q-subtitle1, .q-subtitle2 {
    font-family: var(--q-font-display);
    margin: 0;
}

.q-body1, .q-body2, .q-caption {
    font-family: var(--q-font-body);
    margin: 0;
}

.q-h4 {
    font-size: 2.125rem;
    font-weight: 600;
    line-height: 1.235;
    letter-spacing: -0.01em;
}

.q-h5 {
    font-size: 1.5rem;
    font-weight: 500;
    line-height: 1.334;
    letter-spacing: normal;
}

.q-h6 {
    font-size: 1.25rem;
    font-weight: 500;
    line-height: 1.6;
    letter-spacing: 0.0075em;
}

.q-subtitle1 {
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.75;
    letter-spacing: 0.00938em;
}

.q-subtitle2 {
    font-size: 0.875rem;
    font-weight: 500;
    line-height: 1.57;
    letter-spacing: 0.00714em;
}

.q-body1 {
    font-size: 1rem;
    font-weight: 400;
    line-height: 1.5;
    letter-spacing: 0.00938em;
}

.q-body2 {
    font-size: 0.875rem;
    font-weight: 400;
    line-height: 1.43;
    letter-spacing: 0.01071em;
}

.q-caption {
    font-size: 0.75rem;
    font-weight: 400;
    line-height: 1.66;
    letter-spacing: 0.03333em;
}

/* ── Glyphs ─────────────────────────────────────────────────────────────────
 *
 * The app's own icon and icon-button, replacing MudIcon and MudIconButton. The
 * numbers here are the ones MudBlazor's stylesheet resolved to, so the swap moved
 * nothing: a 24-unit viewBox sized in em, and a round 48px press target.
 *
 * Sizing is font-size on the glyph and 1em for the box, which is what lets a call
 * site override one icon with a single font-size rather than a width/height pair.
 *
 * Tones follow rule 1 above: --primary is the olive sibling, never the marker. */
.q-icon {
    display: inline-block;
    width: 1em;
    height: 1em;
    flex-shrink: 0;
    fill: currentColor;
    user-select: none;
}

.q-icon--sm { font-size: 1.25rem; }
.q-icon--md { font-size: 1.5rem; }
.q-icon--lg { font-size: 2.25rem; }

/* A tone is the call site's explicit word on a glyph's colour, so it outranks
 * whatever colour the surrounding rules would hand down — the same weight the
 * old icon library gave its tone classes, which these replaced. --default is the
 * exception: it is the quiet fallback, and a container may restate it. */
.q-icon--default   { color: var(--q-ink-muted); }
.q-icon--primary   { color: var(--q-accent-text) !important; }
.q-icon--secondary { color: var(--q-ink) !important; }
.q-icon--error     { color: var(--pri-high) !important; }
.q-icon--warning   { color: var(--pri-medium) !important; }
.q-icon--success   { color: var(--pri-low) !important; }
.q-icon--info      { color: var(--q-info) !important; }

.q-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    padding: 12px;
    border: none;
    border-radius: 50%;
    background: transparent;
    color: var(--q-ink-muted);
    font-size: 1.5rem;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
}

.q-icon-btn__label {
    display: flex;
    width: 100%;
    align-items: inherit;
    justify-content: inherit;
}

.q-icon-btn:hover:not(:disabled) {
    background: var(--q-hover);
}

.q-icon-btn:disabled {
    color: var(--q-ink-disabled);
    cursor: default;
}

/* Tones as on .q-icon above. --inherit is a tone too, and the default one: a
 * glyph button takes the colour of the line it sits in unless told otherwise. */
.q-icon-btn--inherit   { color: inherit !important; }
.q-icon-btn--default   { color: var(--q-ink-muted); }
.q-icon-btn--primary   { color: var(--q-accent-text) !important; }
.q-icon-btn--secondary { color: var(--q-ink) !important; }
.q-icon-btn--error     { color: var(--pri-high) !important; }
.q-icon-btn--warning   { color: var(--pri-medium) !important; }
.q-icon-btn--success   { color: var(--pri-low) !important; }
.q-icon-btn--info      { color: var(--q-info) !important; }

/* The one place the marker is correct as-is: a fill with ink laid on it. The
   border matches the fill so the button reads as a solid printed block. */
.btn-primary {
    color: var(--q-accent-ink);
    background-color: var(--q-accent);
    border-color: var(--q-accent);
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem var(--q-surface-raised), 0 0 0 0.25rem var(--q-accent-text);
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--pri-low);
}

.invalid {
    outline: 1px solid var(--pri-high);
}

.validation-message {
    color: var(--pri-high);
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: var(--q-ink-muted);
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ── Daybook brand mark (inline SVG, theme-aware) ─────────────
 * DaybookIcon.razor draws the mark from the global --q-* tokens above, so it
 * follows the edition on its own and needs no palette here. That is why the
 * three blocks of --slate-icon-* overrides this rule used to carry are gone:
 * they described the superseded Quarry stone (cool blue-gray body, tan letter,
 * 22% radius), none of which survives in Diurnal.
 *
 * No drop shadow either. The old mark was a stone and needed lifting off the
 * page; this one is a printed sheet carrying its own box rule, and a shadow
 * would break the flat print register. Corners come from the SVG's own rx,
 * which keeps them at the 2px register rather than a 22% pill.
 * ─────────────────────────────────────────────────────────── */
.slate-icon {
    display: block;
    flex-shrink: 0;
}


/*
 * Daybook task shell — global, loaded AFTER the scoped bundle (see App.razor).
 * Ensures TickTick-style flex layout and dark-theme fields even if scoped CSS order/loading fails.
 */

/* KEEP-IN-SYNC: TaskRow.razor.css — this global twin loads after the scoped
 * bundle and ties on specificity, so it WINS. Any row change must be made in
 * both files or the scoped one silently has no effect. */
.tasks-view .task-row {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    /* Centred, not top-aligned — see the note on .task-row in TaskRow.razor.css.
       The row is a single line, so top alignment only left each part hanging by
       its own height, and the compensating margins stopped adding up once the
       actions box grew to 40px on touch. */
    align-items: center !important;
    gap: 14px;
    padding: 11px 16px;
    border-bottom: 1px solid var(--q-line-soft);
    border-radius: 0;
    margin: 0 14px;
    cursor: pointer;
    min-height: 0;
    box-sizing: border-box;
}

/* No row tint on hover. */
.tasks-view .task-row:hover {
    background: transparent;
}

.tasks-view .task-row--selected {
    background: var(--q-accent-soft) !important;
}

.tasks-view .task-row--completed {
    opacity: 0.55;
}

/* Strike is drawn as an animated gradient line in TaskRow.razor.css (the sweep);
 * this global twin only needs to not re-impose a static text-decoration. */
.tasks-view .task-row--completed .task-row__title {
    text-decoration: none;
}

.tasks-view .task-row__check {
    flex-shrink: 0 !important;
    display: flex !important;
    align-items: center !important;
    cursor: pointer;
}

.tasks-view .task-row__body {
    flex: 1 1 auto !important;
    /* The title keeps some width whatever the row carries; see TaskRow.razor.css. */
    min-width: 6.5rem !important;
    overflow: hidden;
    display: flex !important;
    flex-direction: row !important;
    /* Puts the priority dot on the title's centre line rather than hanging it
       from the cap height and pushing it back down with a margin. */
    align-items: center !important;
    gap: 10px;
}

.tasks-view .task-row__title {
    font-size: 0.98rem;
    line-height: 1.45;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tasks-view .task-row__right {
    display: flex !important;
    flex-direction: row !important;
    align-items: center !important;
    gap: 10px;
    flex-shrink: 0 !important;
}

.tasks-view .task-row__actions {
    flex-shrink: 0 !important;
    opacity: 0;
    transition: opacity 0.12s;
}

.tasks-view .task-row:hover .task-row__actions,
.tasks-view .task-row:focus-within .task-row__actions {
    opacity: 1;
}

/* Touch devices: no hover — keep delete affordance visible */
@media (hover: none) and (pointer: coarse) {
    .tasks-view .task-row__actions {
        opacity: 1;
    }
}

/* A row short of room gives up its extras, least needed first; see TaskRow.razor.css. */
.tasks-view__rows[data-room="m"] .task-row__time-left,
.tasks-view__rows[data-room="s"] .task-row__time-left,
.tasks-view__rows[data-room="xs"] .task-row__time-left,
.tasks-view__rows[data-room="s"] .task-row__reminder,
.tasks-view__rows[data-room="xs"] .task-row__reminder,
.tasks-view__rows[data-room="xs"] .task-row__list-chip {
    display: none;
}

/* Newsprint tooth on the auth pages. The app's own sheet draws its grain from
 * BroadsheetShell.razor.css, which owns the layout root. */
.auth-page::before {
    content: "";
    position: fixed;
    inset: 0;
    background-image: var(--q-grain);
    background-size: 140px 140px;
    opacity: var(--q-grain-opacity);
    pointer-events: none;
    z-index: 1;
}

@media (max-width: 767.98px) {
    .tasks-view__list-scroll {
        padding-bottom: max(28px, env(safe-area-inset-bottom, 0px));
    }

    .tasks-view__group-header {
        padding: 12px 22px 8px;
    }

    /* Five parts share the line now the priority dot is its own control; 9px keeps the
       spacing the four had at 12px, and the width goes to the title. */
    .tasks-view .task-row {
        min-height: 0;
        gap: 9px;
        padding: 13px 6px 13px 14px;
        margin-left: 8px;
        margin-right: 8px;
    }

    .tasks-view .task-row__title {
        font-size: 0.97rem;
    }
}

.tasks-view {
    background: transparent;
}

.tasks-view__group-header {
    padding: 14px 30px 6px;
    background: transparent;
    border-bottom: none;
    position: static;
}

.tasks-view__group-count {
    background: transparent !important;
    padding: 0 4px !important;
    color: var(--q-ink-faint);
    font-weight: 500;
}

.tasks-view .task-row__title {
    color: var(--q-ink);
}

/* Marginalia sits quieter than body copy — ink-faint, not text-secondary. */
.tasks-view .task-row__date,
.tasks-view .task-row__list-name,
.tasks-view .task-row__subtask-badge,
.tasks-view .task-row__reminder {
    color: var(--q-ink-faint);
}

/* ── Account Management Settings (SSR — global) ──
 * Reads the --q-* tokens, which follow the theme App.razor stamps on <html>.
 * That attribute is in the server-rendered HTML for both SSR and interactive pages,
 * so they track the user's chosen Daybook theme (not the OS preference).
 * No prefers-color-scheme media queries needed.
 * ─────────────────────────────────────────────── */
.mgmt-shell {
    display: flex;
    flex-direction: column;
    padding-bottom: 48px;
    font-family: var(--q-font-body);
}

.mgmt-header {
    padding: 32px 36px 0;
}

.mgmt-header__eyebrow {
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--q-accent-text);
    margin: 0 0 8px;
}

.mgmt-header__title {
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: -0.025em;
    color: var(--q-ink);
    margin: 0 0 4px;
    line-height: 1.2;
}

.mgmt-header__subtitle {
    font-size: 0.85rem;
    color: var(--q-ink-muted);
    margin: 0;
}

.mgmt-divider {
    border: none;
    border-top: 1px solid var(--q-line);
    margin: 20px 36px 0;
}

.mgmt-body {
    display: flex;
    gap: 24px;
    padding: 28px 36px;
    align-items: flex-start;
}

/* Sidebar nav */
.mgmt-nav {
    width: 192px;
    flex-shrink: 0;
    position: sticky;
    top: 24px;
}

.mgmt-nav__list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.mgmt-nav__link {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    border-radius: 9px;
    font-size: 0.855rem;
    font-weight: 500;
    color: var(--q-ink-muted);
    text-decoration: none;
    transition: background 0.12s, color 0.12s;
    line-height: 1;
}

.mgmt-nav__link:hover {
    background: var(--q-hover);
    color: var(--q-accent-text);
}

.mgmt-nav__link.active {
    background: color-mix(in srgb, var(--q-accent) 12%, transparent);
    color: var(--q-accent-text);
    font-weight: 600;
}

.mgmt-nav__icon {
    font-size: 17px;
    opacity: 0.55;
    flex-shrink: 0;
    transition: opacity 0.12s;
}

.mgmt-nav__link:hover .mgmt-nav__icon,
.mgmt-nav__link.active .mgmt-nav__icon {
    opacity: 1;
}

/* Content card */
.mgmt-content {
    flex: 1;
    min-width: 0;
    max-width: 600px;
    background: var(--q-surface);
    border-radius: 14px;
    border: 1px solid var(--q-line);
    box-shadow: 0 1px 8px rgba(0,0,0,0.06);
    padding: 28px 32px;
}

.mgmt-content__section-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--q-ink);
    margin: 0 0 22px;
    letter-spacing: -0.01em;
    display: flex;
    align-items: center;
    gap: 8px;
}

.mgmt-content__section-title .material-icons {
    font-size: 20px;
    color: var(--q-accent-text);
    opacity: 0.85;
}

/* Form fields */
.mgmt-field {
    margin-bottom: 20px;
}

.mgmt-field:last-of-type {
    margin-bottom: 0;
}

.mgmt-label {
    display: block;
    font-size: 0.76rem;
    font-weight: 600;
    color: var(--q-ink-muted);
    margin-bottom: 7px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}

.mgmt-input {
    width: 100%;
    padding: 10px 14px;
    font-size: 0.9rem;
    font-family: inherit;
    border: 1.5px solid var(--q-line);
    border-radius: 9px;
    outline: none;
    background: var(--q-bg);
    color: var(--q-ink);
    transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
    box-sizing: border-box;
    line-height: 1.4;
}

.mgmt-input:focus {
    border-color: var(--q-accent-text);
    background: var(--q-surface);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--q-accent) 14%, transparent);
}

.mgmt-input:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

.mgmt-input::placeholder {
    color: var(--q-ink-disabled);
}

.mgmt-validation {
    display: block;
    font-size: 0.78rem;
    color: var(--pri-high);
    margin-top: 5px;
}

.mgmt-hint {
    font-size: 0.78rem;
    color: var(--q-ink-muted);
    margin: 6px 0 0;
    line-height: 1.35;
}

/* A hint that reports something is right: the check takes the low-priority ink,
   which is the sheet's green. */
.mgmt-hint--ok .material-icons {
    font-size: 14px;
    vertical-align: -2px;
    margin-right: 2px;
    color: var(--pri-low);
}

/* A button that has to read as a link mid-sentence: the resend inside the
   email page's hint, which belongs to a different form from the field it sits by. */
.mgmt-link {
    padding: 0;
    border: 0;
    background: none;
    font: inherit;
    color: var(--q-accent-text);
    text-decoration: underline;
    text-underline-offset: 2px;
    cursor: pointer;
}

.mgmt-link:hover {
    color: var(--q-ink);
}

.mgmt-link:focus-visible {
    outline: 2px solid var(--q-accent-text);
    outline-offset: 2px;
    border-radius: 2px;
}

/* The authenticator key: the mono face, spaced in fours the way the page
   prints it, on the sheet's own paper so it reads as a thing to copy. */
.mgmt-key {
    display: inline-block;
    margin: 8px 0 0;
    padding: 10px 14px;
    font-family: var(--q-font-mono);
    font-size: 0.95rem;
    letter-spacing: 0.08em;
    color: var(--q-ink);
    background: var(--q-bg);
    border: 1.5px solid var(--q-line);
    border-radius: 9px;
    user-select: all;
}

/* A six-digit code is typed, not read, so the field is sized to it. */
.mgmt-input--code {
    max-width: 12ch;
    font-family: var(--q-font-mono);
    font-size: 1.1rem;
    letter-spacing: 0.18em;
    text-align: center;
}

/* Ten recovery codes, two to a row, each on its own line for copying. */
.mgmt-codes {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 6px 18px;
    max-width: 36ch;
}

.mgmt-codes li {
    padding: 6px 0;
    border-bottom: 1px solid var(--q-line-soft);
}

.mgmt-codes code {
    font-family: var(--q-font-mono);
    font-size: 0.95rem;
    letter-spacing: 0.06em;
    color: var(--q-ink);
    user-select: all;
}

/* Setup steps: numbered in the mono face because they are a sequence. */
.mgmt-steps {
    list-style: none;
    margin: 0;
    padding: 0;
    counter-reset: step;
}

.mgmt-steps__step {
    position: relative;
    padding: 0 0 22px 40px;
    counter-increment: step;
}

.mgmt-steps__step:last-child {
    padding-bottom: 0;
}

.mgmt-steps__step::before {
    content: counter(step);
    position: absolute;
    left: 0;
    top: 0;
    width: 26px;
    height: 26px;
    display: grid;
    place-items: center;
    font-family: var(--q-font-mono);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--q-accent-ink);
    background: var(--q-accent);
    border-radius: 50%;
}

.mgmt-steps__title {
    margin: 2px 0 4px;
    font-size: 0.95rem;
    font-weight: 600;
    color: var(--q-ink);
}

.mgmt-steps__step .mgmt-hint {
    margin-top: 0;
}

.mgmt-steps__step .mgmt-field {
    margin-top: 12px;
}

/* Linked sign-ins, one to a row: the provider on the left, its button on the right. */
.mgmt-logins {
    list-style: none;
    margin: 16px 0 0;
    padding: 0;
    border-top: 1px solid var(--q-line);
}

.mgmt-logins__row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 12px 0;
    border-bottom: 1px solid var(--q-line);
}

.mgmt-logins__name {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 600;
    color: var(--q-ink);
}

.mgmt-logins__name .material-icons {
    font-size: 20px;
    color: var(--q-ink-faint);
}

.mgmt-logins__row .mgmt-hint {
    margin: 0;
    text-align: right;
}

.mgmt-logins__row form {
    margin: 0;
}

@media (max-width: 640px) {
    .mgmt-codes {
        grid-template-columns: 1fr;
    }
}

/* The plan card's one figure: which plan, set like a heading rather than a field. */
.mgmt-plan__headline,
.mgmt-figure {
    font-family: var(--q-font-display);
    font-size: 1.4rem;
    font-weight: 700;
    line-height: 1.2;
    margin: 0 0 6px;
    color: var(--q-ink);
}

/* The offers: three rows, name and blurb on the left, the price as the button. */
.mgmt-plan__offers-title {
    margin-top: 28px;
}

.mgmt-plan__offers {
    list-style: none;
    margin: 0;
    padding: 0;
    border-top: 1px solid var(--q-line, #e6e2d6);
}

.mgmt-plan__offer {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 14px 0;
    border-bottom: 1px solid var(--q-line, #e6e2d6);
}

.mgmt-plan__offer .mgmt-hint {
    margin-top: 2px;
}

.mgmt-plan__offer-name {
    margin: 0;
    font-weight: 600;
}

/* Alerts — mgmt classes + Bootstrap .alert overrides within the card */
.mgmt-alert,
.mgmt-content .alert {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 16px;
    border-radius: 9px;
    font-size: 0.85rem;
    margin-bottom: 22px;
    line-height: 1.5;
    border: 1px solid transparent;
}

.mgmt-alert--error,
.mgmt-content .alert-danger {
    background: color-mix(in srgb, var(--pri-high) 10%, transparent);
    color: var(--pri-high);
    border-color: color-mix(in srgb, var(--pri-high) 28%, transparent);
}

.mgmt-alert--success,
.mgmt-content .alert-success {
    background: color-mix(in srgb, var(--pri-low) 12%, transparent);
    color: var(--pri-low);
    border-color: color-mix(in srgb, var(--pri-low) 28%, transparent);
}

.mgmt-alert--progress {
    background: var(--q-accent-soft);
    color: var(--q-accent-text);
    border-color: color-mix(in srgb, var(--q-accent) 28%, transparent);
}

.mgmt-alert--warn {
    background: color-mix(in srgb, var(--pri-medium) 12%, transparent);
    color: var(--pri-medium);
    border-color: color-mix(in srgb, var(--pri-medium) 32%, transparent);
}

.mgmt-alert .material-icons {
    flex: 0 0 auto;
    font-size: 18px;
    margin-top: 1px;
}

.mgmt-alert a {
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 2px;
}

/* Settings actions share one hierarchy across profile, security and preferences. */
.mgmt-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-top: 26px;
    padding-top: 22px;
    border-top: 1px solid var(--q-line);
}

.mgmt-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 44px;
    max-width: 100%;
    padding: 10px 16px;
    border: 1px solid transparent;
    border-radius: 8px;
    font-family: inherit;
    font-size: 0.875rem;
    font-weight: 600;
    line-height: 1.35;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.15s, border-color 0.15s, color 0.15s;
}

.mgmt-btn .material-icons { flex: 0 0 auto; line-height: 1; }
.mgmt-btn:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: 3px; }
.mgmt-btn--primary { background: var(--q-accent); color: var(--q-accent-ink); }
.mgmt-btn--primary:hover:not(:disabled):not([aria-disabled="true"]) {
    background: color-mix(in srgb, var(--q-accent) 88%, var(--q-accent-ink));
}
.mgmt-btn--ghost { background: transparent; color: var(--q-ink); border-color: var(--q-line); }
.mgmt-btn--ghost:hover:not(:disabled):not([aria-disabled="true"]) {
    background: var(--q-hover);
    border-color: var(--q-ink-faint);
}
.mgmt-btn--danger {
    background: transparent;
    color: var(--pri-high);
    border-color: color-mix(in srgb, var(--pri-high) 35%, transparent);
}
.mgmt-btn--danger:hover:not(:disabled):not([aria-disabled="true"]) {
    background: color-mix(in srgb, var(--pri-high) 8%, transparent);
    border-color: var(--pri-high);
}
.mgmt-btn:disabled, .mgmt-btn[aria-disabled="true"] { opacity: 0.55; cursor: not-allowed; }
.mgmt-btn[aria-busy="true"] { cursor: progress; }
.mgmt-btn[aria-busy="true"]::after {
    content: "";
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    border: 2px solid currentColor;
    border-right-color: transparent;
    border-radius: 50%;
    animation: q-spin 0.8s linear infinite;
}
@media (prefers-reduced-motion: reduce) {
    .mgmt-btn { transition: none; }
    .mgmt-btn[aria-busy="true"]::after { animation: none; border-style: dotted; }
}

.notification-settings {
    display: flex;
    flex-direction: column;
    gap: 18px;
}

.notification-settings__hero {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 16px;
    align-items: flex-start;
    padding: 18px;
    border-radius: 16px;
    background: linear-gradient(135deg, color-mix(in srgb, var(--q-accent) 12%, transparent), color-mix(in srgb, var(--q-accent) 5%, transparent));
    border: 1px solid color-mix(in srgb, var(--q-accent) 18%, transparent);
}

.notification-settings__status {
    width: 48px;
    height: 48px;
    border-radius: 16px;
    display: grid;
    place-items: center;
    color: #fff;
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.12);
}

.notification-settings__status .material-icons {
    font-size: 25px;
}

.notification-settings__status--success {
    background: linear-gradient(135deg, var(--pri-low), color-mix(in srgb, var(--pri-low) 60%, white));
}

.notification-settings__status--warning {
    background: linear-gradient(135deg, var(--pri-medium), color-mix(in srgb, var(--pri-medium) 60%, white));
}

.notification-settings__status--neutral {
    background: linear-gradient(135deg, var(--q-accent), color-mix(in srgb, var(--q-accent) 60%, white));
}

.notification-settings__eyebrow {
    margin: 0 0 4px;
    color: var(--q-accent-text);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.notification-settings__hero h3,
.notification-settings__guide h3 {
    margin: 0 0 6px;
    color: var(--q-ink);
    font-size: 1.05rem;
    letter-spacing: -0.01em;
}

.notification-settings__hero p,
.notification-settings__guide p {
    margin: 0;
    color: var(--q-ink-muted);
    font-size: 0.88rem;
    line-height: 1.5;
}

.notification-settings__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}

.notification-settings__actions .mgmt-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
    box-shadow: none;
}

.notification-settings__facts {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 10px;
    margin: 0;
}

.notification-settings__facts div {
    padding: 14px;
    border-radius: 13px;
    background: var(--q-bg);
    border: 1px solid var(--q-line);
}

.notification-settings__facts dt {
    margin-bottom: 4px;
    color: var(--q-ink-muted);
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.notification-settings__facts dd {
    margin: 0;
    color: var(--q-ink);
    font-size: 0.9rem;
    font-weight: 600;
}

.notification-settings__guide {
    padding: 18px;
    border-radius: 14px;
    background: var(--q-surface);
    border: 1px dashed color-mix(in srgb, var(--q-accent) 36%, transparent);
}

.notification-settings__guide ol {
    margin: 12px 0 0;
    padding-left: 20px;
    color: var(--q-ink);
    font-size: 0.88rem;
    line-height: 1.6;
}

@media (max-width: 720px) {
    .mgmt-input {
        font-size: 16px;
        padding: 12px 14px;
    }
    .mgmt-btn { min-height: 44px; }
    .mgmt-nav__link {
        min-height: 44px;
        padding: 12px 14px;
    }
    .mgmt-body {
        flex-direction: column;
        padding: 16px 16px max(32px, env(safe-area-inset-bottom, 0px));
        gap: 16px;
    }
    .mgmt-nav {
        width: 100%;
        position: static;
    }
    .mgmt-nav__list {
        flex-direction: row;
        flex-wrap: wrap;
    }
    .mgmt-header {
        padding: 20px 16px 0;
    }
    .mgmt-divider {
        margin: 16px 16px 0;
    }
    .mgmt-content {
        padding: 20px;
    }
    .notification-settings__hero,
    .notification-settings__facts {
        grid-template-columns: 1fr;
    }
}

/*
 * iOS Safari auto-zooms when a focused input/textarea has computed font-size below 16px.
 * Phone landscape often exceeds 768px width, so max-width-only rules miss those viewports.
 * Touch-primary devices get 16px on form fields regardless of width (desktop mouse UIs unchanged).
 */
@media (hover: none) and (pointer: coarse) {
    .tasks-view__add-input,
    .composer__mirror, /* the add line's marks are set on a copy of its words, in the same size */
    .cmd-input,
    .time-slot-picker__field-input,
    .reminder-panel__custom-input,
    .tasks-view__detail-col .detail-subtask__input,
    .tasks-view__detail-col .detail-comment-field__input {
        font-size: 16px !important;
    }
}

/* Week calendar resize preview (appended by week-cal-resize.js — outside Blazor scoped CSS) */
.week-cal__block-resize-ghost {
    display: flex;
    flex-direction: column;
    align-items: stretch;
    overflow: hidden;
    border-radius: 6px;
    border: 1px solid color-mix(in srgb, var(--q-accent) 40%, transparent);
    border-left: 3px solid var(--q-accent-text);
    background: color-mix(in srgb, var(--q-accent) 16%, var(--q-surface));
    color: var(--q-ink);
    box-shadow: var(--q-shadow-2);
}

.week-cal__block-resize-ghost.week-cal__p-high {
    border-left-color: var(--pri-high);
    background: color-mix(in srgb, var(--pri-high) 18%, var(--q-surface));
}

.week-cal__block-resize-ghost.week-cal__p-medium {
    border-left-color: var(--pri-medium);
    background: color-mix(in srgb, var(--pri-medium) 16%, var(--q-surface));
}

.week-cal__block-resize-ghost.week-cal__p-low {
    border-left-color: var(--pri-low);
    background: color-mix(in srgb, var(--pri-low) 14%, var(--q-surface));
}

.week-cal__block-resize-ghost .week-cal__block-row {
    flex: 1 1 0;
    min-height: 0;
    display: flex;
    flex-direction: row;
    align-items: stretch;
    padding: 4px 0;
}

.week-cal__block-resize-ghost .week-cal__block-grip {
    flex: 0 0 18px;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: 2px;
    color: rgba(0, 0, 0, 0.38);
    opacity: 0.55;
}

.week-cal__block-resize-ghost .q-icon {
    font-size: 14px !important;
    width: 14px !important;
    height: 14px !important;
}

.theme-dark .week-cal__block-resize-ghost .week-cal__block-grip {
    color: rgba(255, 255, 255, 0.45);
}

.week-cal__block-resize-ghost .week-cal__block {
    flex: 1 1 0;
    min-width: 0;
    margin: 0;
    padding: 2px 6px 2px 0;
    border: 0;
    background: transparent;
    text-align: left;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    gap: 2px;
    font: inherit;
    color: inherit;
    cursor: default;
    overflow: hidden;
}

.week-cal__block-resize-ghost .week-cal__block--dense-move {
    flex-direction: row !important;
    align-items: center !important;
    gap: 8px !important;
}

.week-cal__block-resize-ghost .week-cal__block-title {
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.25;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    width: 100%;
}

.week-cal__block-resize-ghost .week-cal__block-time {
    font-size: 0.66rem;
    font-weight: 500;
    opacity: 0.82;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* ═══════════════════════════════════════════════════════════════════════════
 * THE PUBLIC SHEET — the signed-out pages: the front page (/), Sign in,
 * Create an account, Privacy and Support (Components/Account/Shared/
 * NewsstandSheet.razor and the pages that use it).
 *
 * The same paper, ink and type as the app, with the daybreak mark over the
 * wordmark. The `newsstand` class names are the ones the block was built
 * under and are kept for that reason only: nothing on these pages should read
 * as a newspaper, and no rule here should draw one.
 *
 * GLOBAL AND UNLAYERED ON PURPOSE (two reasons, both load-bearing):
 *  1. The fields are rendered by <InputText>/<InputCheckbox>. CSS isolation
 *     stamps its scope attribute only on markup the component itself writes, so
 *     a Login.razor.css would never reach those inputs.
 *  2. The element reset (Styles/tailwind.css, in its base layer) normalizes
 *     raw input/button. Being unlayered, these rules beat it whatever its
 *     specificity, so nothing in that reset can undo them.
 *
 * The page carries `auth-page` alongside `newsstand`: that class is what flips
 * the token table to Nocturne off the OS scheme on static SSR pages, and what
 * lays the paper grain over the sheet. Do not drop it.
 *
 * Every load animation's BASE rule is its finished state and the keyframes run
 * from the hidden one, so `animation: none` under reduced motion leaves the page
 * fully composed rather than blank.
 * ═══════════════════════════════════════════════════════════════════════════ */

/* body sets overflow:hidden for the app shell, so this element owns the scroll
   the same way .bs does. */
.newsstand {
    height: 100dvh;
    overflow-y: auto;
    box-sizing: border-box;
    padding: 24px 28px 40px;
    padding-left: max(28px, env(safe-area-inset-left, 0px));
    padding-right: max(28px, env(safe-area-inset-right, 0px));
    background: var(--q-bg);
    color: var(--q-ink);
    font-family: var(--q-font-body);
    display: flex;
    flex-direction: column;
}

/* `margin-block: auto` centers the sheet on a tall screen and still lets it
   scroll from the top when it overflows a short one — `justify-content: center`
   would clip the header off the top edge instead. */
.newsstand__sheet {
    width: 100%;
    max-width: 1120px;
    margin: auto;
}

@keyframes ns-rise {
    from { opacity: 0; transform: translateY(10px); }
}

@keyframes ns-wipe {
    from { transform: scaleX(0); }
}

/* ── Header: the mark, the wordmark, the date ───────────────────────────── */
.newsstand__mast {
    padding: clamp(6px, 1.6vw, 18px) 0 clamp(14px, 2vw, 22px);
    text-align: center;
}

.newsstand__mark-well {
    display: flex;
    justify-content: center;
    margin-bottom: clamp(6px, 1.2vw, 12px);
    animation: ns-rise 0.5s ease both;
}

/* The daybreak mark — the App Store icon's picture in the page's own colours.
   The sun is the marker: a fill, which is what the marker is for. It comes up
   from behind the foot of the book with a little overshoot, as the iPhone
   app's spring does. The base rule is the risen position; the keyframes run
   from the sunk one, so reduced motion leaves it up. */
.daybreak {
    display: block;
    overflow: visible;
}

.daybreak__sun {
    fill: var(--q-accent);
    animation: ns-sunrise 0.9s cubic-bezier(0.34, 1.3, 0.5, 1) 0.15s both;
}

@keyframes ns-sunrise {
    from { transform: translateY(59px); }
}

.daybreak__page {
    fill: var(--q-surface);
}

.daybreak__edge {
    fill: none;
    stroke: var(--q-ink);
    stroke-opacity: 0.3;
    stroke-width: 1;
}

.daybreak__rule {
    fill: none;
    stroke: var(--q-ink);
    stroke-width: 1.5;
    stroke-linejoin: round;
}

/* Fraunces is loaded with its SOFT and WONK axes (see App.razor). The wordmark
   is the one place that spends them: WONK swaps in the flared alternates and
   opsz 144 is the display cut. The iPhone app sets the same word over the same
   mark on its sign-in page. */
.newsstand__wordmark {
    margin: 0;
    font-family: var(--q-font-display);
    font-weight: 600;
    font-size: clamp(2.8rem, 7vw, 4.6rem);
    font-variation-settings: "opsz" 144, "SOFT" 0, "WONK" 1;
    letter-spacing: -0.035em;
    line-height: 0.95;
    color: var(--q-ink);
    text-shadow: var(--q-press);
    animation: ns-rise 0.62s cubic-bezier(0.22, 0.9, 0.3, 1) 0.06s both;
}

.newsstand__creed {
    margin: 10px 0 0;
    font-family: var(--q-font-mono);
    font-size: 0.66rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--q-ink-muted);
    animation: ns-rise 0.5s ease 0.16s both;
}

/* One rule under the header. */
.newsstand__rule {
    height: 1px;
    background: var(--q-ink);
    transform-origin: left center;
    animation: ns-wipe 0.6s cubic-bezier(0.22, 0.9, 0.3, 1) 0.22s both;
}

/* ── Two columns ────────────────────────────────────────────────────────── */
.newsstand__cols {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 384px;
    margin-top: clamp(28px, 3.4vw, 44px);
}

.newsstand__leader {
    min-width: 0;
    padding-right: clamp(28px, 4vw, 48px);
    border-right: 1px solid var(--q-line);
    animation: ns-rise 0.6s ease 0.32s both;
}

.newsstand__kicker {
    margin: 0 0 10px;
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    font-weight: 500;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--q-accent-text);
}

.newsstand__head {
    position: relative;
    isolation: isolate;
    margin: 0 0 18px;
    font-family: var(--q-font-display);
    font-weight: 600;
    font-size: clamp(1.9rem, 3.4vw, 2.9rem);
    line-height: 1.05;
    letter-spacing: -0.025em;
    color: var(--q-ink);
    text-shadow: var(--q-press);
}

/* Keep the whole glyph on the marker, including when a phrase wraps.
   Paint ink and fill together so dark-mode text never precedes its backdrop. */
.newsstand__mark {
    color: var(--q-accent-ink);
    background: var(--q-accent);
    padding: 0.02em 0.06em;
    border-radius: 0.12em;
    -webkit-box-decoration-break: clone;
    box-decoration-break: clone;
    text-shadow: none;
}

.newsstand__lead {
    max-width: 56ch;
    font-size: 0.95rem;
    line-height: 1.62;
    color: var(--q-ink-muted);
}

.newsstand__lead p {
    margin: 0 0 0.9em;
}

.newsstand__lead p:last-child {
    margin-bottom: 0;
}

/* Three short points under the lead, marked with the marker's dot. */
.newsstand__notice-list {
    margin: clamp(20px, 3vw, 28px) 0 0;
    padding: 16px 0 0;
    border-top: 1px solid var(--q-line-soft);
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 9px;
    max-width: 56ch;
    font-size: 0.86rem;
    line-height: 1.5;
    color: var(--q-ink-muted);
}

.newsstand__notice-list li {
    position: relative;
    padding-left: 18px;
}

.newsstand__notice-list li::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.55em;
    width: 7px;
    height: 7px;
    background: var(--q-accent);
}

/* ── The card ───────────────────────────────────────────────────────────── */
.newsstand__coupon-well {
    padding-left: clamp(28px, 4vw, 48px);
    animation: ns-clip 0.62s cubic-bezier(0.22, 0.9, 0.3, 1) 0.4s both;
}

@keyframes ns-clip {
    from { opacity: 0; transform: translateY(-12px); }
}

/* The form on a raised card, ruled with a hairline and lifted with a shadow.
   Square corners, as the app's own surfaces are. */
.newsstand__coupon {
    position: relative;
    padding: 28px 28px 26px;
    border: 1px solid var(--q-line);
    background: var(--q-surface-raised);
    box-shadow: var(--q-shadow-2);
}

.newsstand__coupon-title {
    margin: 0 0 22px;
    font-family: var(--q-font-display);
    font-weight: 600;
    font-size: 1.75rem;
    letter-spacing: -0.025em;
    line-height: 1;
    color: var(--q-ink);
}

/* Vermilion means late, and nothing else — on a form the same alarm is spent on
   the one thing that went wrong. */
.newsstand__erratum {
    margin-bottom: 20px;
    padding: 9px 12px;
    border-left: 3px solid var(--pri-high);
    background: color-mix(in srgb, var(--pri-high) 9%, transparent);
    font-size: 0.84rem;
    line-height: 1.45;
    color: var(--pri-high);
}

/* ── Fields: ruled lines, not boxes ─────────────────────────────────────── */
.newsstand__field {
    margin-bottom: 19px;
}

.newsstand__label-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.newsstand__label {
    display: block;
    margin: 0 0 3px;
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
    transition: color 150ms ease;
}

.newsstand__field:focus-within .newsstand__label {
    color: var(--q-accent-text);
}

.newsstand__label-link {
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
    text-decoration: none;
}

.newsstand__label-link:hover {
    color: var(--q-accent-text);
    text-decoration: underline;
}

.newsstand__input {
    display: block;
    width: 100%;
    box-sizing: border-box;
    padding: 7px 2px 8px;
    border: 0;
    border-bottom: 1.5px solid var(--q-line);
    border-radius: 0;
    background: transparent;
    font-family: var(--q-font-body);
    /* 16px — anything smaller and iOS Safari zooms the focused field. */
    font-size: 1rem;
    line-height: 1.35;
    color: var(--q-ink);
    outline: none;
    transition: border-color 150ms ease, box-shadow 150ms ease;
}

.newsstand__input::placeholder {
    color: var(--q-ink-faint);
    opacity: 0.65;
}

/* The rule darkens and doubles rather than growing a focus ring. box-shadow,
   not border-width, so nothing reflows. */
.newsstand__input:focus {
    border-bottom-color: var(--q-accent-text);
    box-shadow: 0 1.5px 0 0 var(--q-accent-text);
}

/* Chrome paints autofilled fields with its own opaque background, which on a
   transparent ruled input shows up as a block sitting on the card. */
.newsstand__input:-webkit-autofill,
.newsstand__input:-webkit-autofill:hover,
.newsstand__input:-webkit-autofill:focus {
    -webkit-text-fill-color: var(--q-ink);
    -webkit-box-shadow: inset 0 0 0 100px var(--q-surface-raised);
    caret-color: var(--q-ink);
}

.newsstand__validation {
    display: block;
    margin-top: 5px;
    font-size: 0.76rem;
    color: var(--pri-high);
}

/* Blazor stamps .invalid on failed fields; app.css gives that a full outline,
   which on a ruled field boxes in the one control that has no box. */
.newsstand__input.invalid {
    outline: none;
    border-bottom-color: var(--pri-high);
}

/* ── Keep me signed in ──────────────────────────────────────────────────── */
.newsstand__keep {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: 22px;
    font-size: 0.84rem;
    color: var(--q-ink-muted);
    cursor: pointer;
    user-select: none;
}

/* A square tick box, filled with the marker when set — accent as a fill with
   accent-ink laid on it, never as the tick's own color. */
.newsstand__check {
    appearance: none;
    -webkit-appearance: none;
    flex-shrink: 0;
    width: 15px;
    height: 15px;
    margin: 0;
    padding: 0;
    border: 1.5px solid var(--q-ink-faint);
    border-radius: 0;
    background: transparent;
    background-position: center;
    background-repeat: no-repeat;
    background-size: 11px 11px;
    cursor: pointer;
    transition: background-color 130ms ease, border-color 130ms ease;
}

.newsstand__check:checked {
    border-color: var(--q-accent);
    background-color: var(--q-accent);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2316140f' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
}

.newsstand__check:focus-visible {
    outline: 2px solid var(--q-accent-text);
    outline-offset: 2px;
}

/* Small print on the card — what happens after it is sent. No rule of its own:
   it follows a ruled field, and a border here lands a second hairline a few
   pixels under the field's own. */
.newsstand__note {
    margin: -2px 0 18px;
    font-size: 0.78rem;
    line-height: 1.5;
    color: var(--q-ink-faint);
}

/* ── The primary button ─────────────────────────────────────────────────── */
.newsstand__stamp {
    display: block;
    width: 100%;
    padding: 13px 20px;
    border: 0;
    border-radius: var(--radius-sm);
    background: var(--q-accent);
    color: var(--q-accent-ink);
    font-family: var(--q-font-mono);
    font-size: 0.74rem;
    font-weight: 600;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    text-indent: 0.26em; /* centers wide tracking, which hangs right otherwise */
    cursor: pointer;
    transition: background-color 130ms ease, transform 90ms ease, box-shadow 130ms ease;
}

.newsstand__stamp:hover {
    background: var(--q-accent-hover);
    box-shadow: 0 3px 10px color-mix(in srgb, var(--q-accent) 34%, transparent);
}

.newsstand__stamp:active {
    transform: translateY(1px);
    box-shadow: none;
}

.newsstand__stamp:focus-visible {
    outline: 2px solid var(--q-accent-text);
    outline-offset: 2px;
}

.newsstand__or {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 16px 0;
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
}

.newsstand__or::before,
.newsstand__or::after {
    content: "";
    flex: 1;
    height: 1px;
    background: var(--q-line);
}

.newsstand__alt {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 12px 20px;
    border: 1px solid var(--q-line);
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--q-ink-muted);
    font-family: var(--q-font-mono);
    font-size: 0.68rem;
    font-weight: 500;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    cursor: pointer;
    transition: border-color 130ms ease, color 130ms ease, background-color 130ms ease;
}

.newsstand__alt:hover {
    border-color: var(--q-accent-text);
    color: var(--q-accent-text);
    background: var(--q-accent-softer);
}

.newsstand__alt:focus-visible {
    outline: 2px solid var(--q-accent-text);
    outline-offset: 2px;
}

/* PasskeySubmit marks its button while the passkey prompt is open or the answer is on its way. */
button[name="__passkeySubmit"][aria-busy="true"] {
    cursor: progress;
    opacity: 0.6;
}

/* Sits outside the card: the other way in. */
.newsstand__subscribe {
    margin: 18px 0 0;
    text-align: center;
    font-size: 0.85rem;
    color: var(--q-ink-muted);
}

.newsstand__subscribe a {
    color: var(--q-accent-text);
    font-weight: 600;
    text-decoration: none;
}

.newsstand__subscribe a:hover {
    text-decoration: underline;
}

/* ── Footer ─────────────────────────────────────────────────────────────── */

/* The links the App Store listing points at. Every page carries it, so a
   reviewer who lands on the sign-in page can still reach Privacy and Support. */
.newsstand__colophon {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 6px 24px;
    margin-top: clamp(30px, 4vw, 48px);
    padding-top: 14px;
    border-top: 1px solid var(--q-line);
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    animation: ns-rise 0.5s ease 0.52s both;
}

.newsstand__colophon a {
    color: var(--q-ink-faint);
    text-decoration: none;
    transition: color 150ms ease;
}

.newsstand__colophon a:hover {
    color: var(--q-accent-text);
    text-decoration: underline;
}

.newsstand__colophon a:focus-visible {
    outline: 2px solid var(--q-accent-text);
    outline-offset: 3px;
}

/* ── The front page (Landing) ───────────────────────────────────────────── */

/* The sample is wider than the form: it has a date to set and four rows to rule. */
.newsstand--front .newsstand__cols {
    grid-template-columns: minmax(0, 1fr) 420px;
    align-items: start;
}

.front__head {
    max-width: 13ch;
    font-size: clamp(2.3rem, 4.8vw, 4rem);
}

/* The primary action and the alternative, side by side. They are links here,
   not buttons, so they take the form's classes and give up its full width. */
.front__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-top: 26px;
}

.front__stamp,
.front__alt {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: auto;
    box-sizing: border-box;
    padding-left: 26px;
    padding-right: 26px;
    text-decoration: none;
}

.front__fine {
    margin: 14px 0 0;
    font-size: 0.8rem;
    line-height: 1.5;
    color: var(--q-ink-faint);
}

.front__fine a {
    color: var(--q-accent-text);
    font-weight: 600;
    text-decoration: none;
}

.front__fine a:hover {
    text-decoration: underline;
}

/* The sample — today's page as the app shows it, on the same raised card as the
   form. Nothing in it is live. */
.proof {
    position: relative;
    margin: 0;
    padding: 18px 20px 16px;
    border: 1px solid var(--q-line);
    background: var(--q-surface-raised);
    box-shadow: var(--q-shadow-2);
    color: var(--q-ink);
}

.proof__kicker {
    margin: 0 0 8px;
    font-family: var(--q-font-mono);
    font-size: 0.58rem;
    font-weight: 500;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--q-accent-text);
}

/* The dateline, as the app's own header sets it: the day in display type, the
   joining words in the italic. */
.proof__date {
    margin: 0 0 10px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--q-ink);
    font-family: var(--q-font-display);
    font-weight: 600;
    font-size: 1.5rem;
    letter-spacing: -0.02em;
    line-height: 1.05;
    color: var(--q-ink);
}

.proof__date-the,
.proof__date-month {
    font-style: italic;
    font-weight: 400;
    color: var(--q-ink-muted);
}

.proof__ord {
    margin-left: 1px;
    font-size: 0.55em;
    line-height: 0;
    vertical-align: super;
}

.proof__conditions {
    margin: 0 0 4px;
    font-family: var(--q-font-mono);
    font-size: 0.58rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
}

.proof__rows {
    margin: 0;
    padding: 0;
    list-style: none;
}

.proof__row {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 8px 0;
    border-bottom: 1px solid var(--q-line-soft);
    font-size: 0.9rem;
    line-height: 1.4;
}

.proof__row:last-child {
    border-bottom: 0;
}

/* The task row's tick box: square, ruled, filled with the marker when done. */
.proof__check {
    flex: 0 0 14px;
    width: 14px;
    height: 14px;
    box-sizing: border-box;
    border: 1.5px solid var(--q-ink-faint);
}

.proof__check--done {
    border-color: var(--q-accent);
    background-color: var(--q-accent);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2316140f' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
    background-position: center;
    background-repeat: no-repeat;
    background-size: 10px 10px;
}

/* Priority is a dot, never type — the app's rule for it. */
.proof__dot {
    flex: 0 0 6px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
}

.proof__dot--high   { background: var(--pri-high); }
.proof__dot--medium { background: var(--pri-medium); }
.proof__dot--low    { background: var(--pri-low); }
.proof__dot--none   { background: var(--pri-none); }

.proof__title {
    flex: 1;
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.proof__row--done .proof__title {
    color: var(--q-ink-faint);
    text-decoration: line-through;
    text-decoration-thickness: 1.5px;
    text-decoration-color: var(--q-ink-faint);
}

.proof__meta {
    flex-shrink: 0;
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
}

/* Vermilion means late, and nothing else. */
.proof__meta--late {
    color: var(--pri-high);
}

/* Under a rule: the clock, a habit and a countdown, as the app keeps them
   beside the day. */
.proof__margin {
    display: grid;
    gap: 8px;
    margin: 14px 0 0;
    padding-top: 12px;
    border-top: 1px solid var(--q-line);
}

.proof__margin > div {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    font-size: 0.8rem;
    color: var(--q-ink-muted);
}

.proof__margin dt {
    font-family: var(--q-font-mono);
    font-size: 0.56rem;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
}

.proof__margin dd {
    margin: 0;
    text-align: right;
}

/* ── Under the columns: what's in it ────────────────────────────────────── */
.newsstand__below {
    margin-top: clamp(28px, 4vw, 44px);
    padding-top: 18px;
    border-top: 1px solid var(--q-line);
    animation: ns-rise 0.6s ease 0.5s both;
}

.front__sections {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 20px 28px;
    margin: 0;
}

.front__sections > div {
    padding-left: 12px;
    border-left: 1px solid var(--q-line);
}

.front__sections dt {
    margin-bottom: 4px;
    font-family: var(--q-font-display);
    font-weight: 600;
    font-size: 1.05rem;
    letter-spacing: -0.01em;
    color: var(--q-ink);
}

.front__sections dd {
    margin: 0;
    font-size: 0.84rem;
    line-height: 1.5;
    color: var(--q-ink-muted);
}

/* ── One measure to be read (Privacy, Support) ──────────────────────────── */
.newsstand__page {
    margin-top: clamp(28px, 3.4vw, 44px);
    animation: ns-rise 0.6s ease 0.32s both;
}

.notice {
    max-width: 66ch;
    margin: 0 auto;
}

.notice__title {
    margin: 0 0 6px;
    font-family: var(--q-font-display);
    font-weight: 600;
    font-size: clamp(2rem, 4vw, 3rem);
    letter-spacing: -0.025em;
    line-height: 1;
    color: var(--q-ink);
    text-shadow: var(--q-press);
}

.notice__dateline {
    margin: 0 0 22px;
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
}

.notice__lede {
    margin: 0 0 8px;
    font-size: 1.02rem;
    line-height: 1.62;
    color: var(--q-ink);
}

.notice h3 {
    margin: 26px 0 8px;
    padding-top: 12px;
    border-top: 1px solid var(--q-line-soft);
    font-family: var(--q-font-display);
    font-weight: 600;
    font-size: 1.25rem;
    letter-spacing: -0.015em;
    line-height: 1.2;
    color: var(--q-ink);
}

.notice p,
.notice li {
    font-size: 0.95rem;
    line-height: 1.62;
    color: var(--q-ink-muted);
}

.notice p {
    margin: 0 0 0.9em;
}

.notice ul {
    margin: 0 0 0.9em;
    padding-left: 1.1em;
}

.notice li {
    margin-bottom: 0.5em;
}

.notice strong {
    font-weight: 600;
    color: var(--q-ink);
}

.notice a {
    color: var(--q-accent-text);
    font-weight: 600;
    text-decoration: none;
}

.notice a:hover {
    text-decoration: underline;
}

.notice a:focus-visible {
    outline: 2px solid var(--q-accent-text);
    outline-offset: 2px;
}

/* ══ Narrower screens ═════════════════════════════════════════════════════ */
@media (max-width: 1023.98px) {
    .front__sections {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
}

/* ══ < 900px — one column ═══════════════════════════════════════════════════
   The sign-in page puts the form first, because that is what the reader came
   for; the front page puts the leader first, because the reader came to find
   out what this is. */
@media (max-width: 899.98px) {
    .newsstand {
        padding: 18px 20px 40px;
    }

    .newsstand__cols {
        display: flex;
        flex-direction: column;
        gap: 30px;
    }

    .newsstand__coupon-well {
        order: -1;
        padding-left: 0;
        animation-delay: 0.32s;
    }

    .newsstand__leader {
        padding-right: 0;
        padding-top: 26px;
        border-right: 0;
        border-top: 1px solid var(--q-line);
        animation-delay: 0.42s;
    }

    .newsstand--front .newsstand__cols {
        gap: 34px;
    }

    .newsstand--front .newsstand__coupon-well {
        order: 0;
        animation-delay: 0.42s;
    }

    .newsstand--front .newsstand__leader {
        padding-top: 0;
        border-top: 0;
        animation-delay: 0.32s;
    }

    .proof {
        max-width: 480px;
        margin: 0 auto;
    }
}

/* ══ < 560px ══════════════════════════════════════════════════════════════ */
@media (max-width: 559.98px) {
    .newsstand {
        padding: 14px 14px 32px;
    }

    .newsstand__mark-well .daybreak {
        width: 64px;
        height: 48px;
    }

    .newsstand__creed {
        font-size: 0.6rem;
        letter-spacing: 0.14em;
    }

    .newsstand__coupon {
        padding: 24px 18px 22px;
    }

    .newsstand__stamp,
    .newsstand__alt {
        min-height: 46px;
    }

    .front__head {
        max-width: none;
    }

    .front__actions a {
        width: 100%;
    }

    .proof {
        padding: 16px 14px 14px;
    }

    .front__sections {
        grid-template-columns: minmax(0, 1fr);
        gap: 16px;
    }

    .newsstand__colophon {
        gap: 6px 18px;
    }
}

@media (prefers-reduced-motion: reduce) {
    .newsstand *,
    .newsstand *::before,
    .newsstand *::after {
        animation: none !important;
    }
}

/* Screen-reader / programmatic click targets (avoid display:none — iOS may skip .click()) */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE REGISTER — assets and their upkeep
   ───────────────────────────────────────────────────────────────────────────
   Global rather than scoped, and deliberately so: this one surface is drawn by
   five components (AssetsPage, AssetPage, ServiceLogDialog, PhotoStrip,
   PhotoPicker), and Blazor's scoped CSS cannot cross a component boundary.
   Splitting it — some scoped, some here — is how a rule ends up defined twice
   with the global copy quietly winning, which is a trap this codebase has
   already been caught by once. One definition, one place.

   The register is the same printed ledger column the timesheet is: headings in
   the display face, rows ruled, every figure hung right in tabular mono. No
   table — the app still has no .q-table primitive (D5), and a register really
   is a ledger column rather than a grid.

   Two gutters hold the columns: --rg-meter and --rg-money. Group heads, year
   heads and entries all reserve them, so the figures line up whatever a row
   happens to say. Break that and the columns stop reading as columns.
   ═══════════════════════════════════════════════════════════════════════════ */

.register,
.asset {
    --rg-measure: 900px;
    --rg-meter: 5.4rem;
    --rg-money: 5.4rem;
    --rg-bleed: 8px;
    /* The shell hands the page column over flush — .bs__page carries no padding
       of its own — so the ledger sets its own gutters, the way the timesheet
       does. It must stay wider than --rg-bleed, or a bled row crosses the index
       rule on one side and the edge of the sheet on the other. */
    --rg-gutter: 0px;

    max-width: calc(var(--rg-measure) + var(--rg-gutter) * 2);
    padding: 0 var(--rg-gutter) 56px;
    box-sizing: border-box;
}

/* Only the wide sheet rules a line down the left of the page column, and type
   set hard against that rule reads as a printing fault. Below 1024px the index
   is a strip overhead and the shell's own padding is already the gutter. */
@media (min-width: 1024px) {
    .register,
    .asset { --rg-gutter: 24px; }
}

.register__bar,
.asset__bar {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-bottom: 8px;
}

.asset__spacer { flex: 1; }

/* ── Shared ledger primitives ───────────────────────────────────────────── */

.register__rule {
    flex: 1 1 auto;
    min-width: 14px;
    height: 0;
    margin: 0 8px 0.34em;
    border-bottom: 1px dotted var(--q-line);
    align-self: flex-end;
}

.register__figure {
    font-family: var(--q-font-mono);
    font-size: 0.78rem;
    font-variant-numeric: tabular-nums;
    text-align: right;
    color: var(--q-ink);
}

.register__figure--meter { color: var(--q-ink-muted); }
.register__figure--group { font-size: 0.82rem; font-weight: 600; }

/* ── The register: groups and rows ──────────────────────────────────────── */

.register__group { margin-top: 28px; }

.register__group-head {
    display: grid;
    grid-template-columns: auto 1fr var(--rg-money);
    align-items: baseline;
    gap: 0 10px;
    padding-bottom: 7px;
    border-bottom: 1.5px solid color-mix(in srgb, var(--q-ink) 30%, var(--q-line));
}

.register__group-name {
    font-family: var(--q-font-display);
    font-size: 1.02rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--q-ink);
}

.register__row {
    display: grid;
    grid-template-columns: 8px minmax(0, 11em) minmax(0, 1fr) var(--rg-meter) var(--rg-money);
    align-items: center;
    gap: 0 10px;
    width: calc(100% + var(--rg-bleed) * 2);
    margin: 0 calc(var(--rg-bleed) * -1);
    padding: 10px var(--rg-bleed);
    border: none;
    border-bottom: 1px solid var(--q-line-soft);
    background: none;
    font: inherit;
    text-align: left;
    color: var(--q-ink);
    cursor: pointer;
    transition: background-color 0.12s;
    box-sizing: border-box;
}

.register__row:hover { background: color-mix(in srgb, var(--q-ink) 5%, transparent); }
.register__row:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: -2px; }

/* The asset's color is always a mark, never type — the ink stays readable and
   a badly chosen swatch cannot wreck contrast. */
.register__dot,
.asset__bar-mark {
    flex-shrink: 0;
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

.register__name {
    font-size: 0.9rem;
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.register__lead,
.asset__entry-lead {
    display: flex;
    align-items: baseline;
    gap: 8px;
    min-width: 0;
}

.register__sub {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.82rem;
    color: var(--q-ink-muted);
}

.register__empty {
    margin-top: 40px;
    padding-top: 20px;
    border-top: 1.5px solid var(--q-line);
    max-width: 46ch;
}

.register__empty-line {
    font-family: var(--q-font-display);
    font-size: 1.1rem;
    font-weight: 600;
    margin: 0 0 6px;
    color: var(--q-ink);
}

.register__empty-note { margin: 0; font-size: 0.9rem; color: var(--q-ink-muted); }

/* ── One asset ──────────────────────────────────────────────────────────── */

.asset__missing { margin-top: 40px; color: var(--q-ink-muted); }

.asset__head {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    margin-top: 20px;
}

.asset__bar-mark {
    width: 4px;
    height: 2.6rem;
    border-radius: 2px;
    margin-top: 4px;
}

.asset__name {
    font-family: var(--q-font-display);
    font-size: 1.9rem;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.1;
    margin: 0;
    color: var(--q-ink);
}

.asset__made {
    margin: 4px 0 0;
    font-size: 0.86rem;
    color: var(--q-ink-muted);
}

/* The figures that answer "what is it on, and what has it cost" without
   reading the history. */
.asset__figures {
    display: flex;
    flex-wrap: wrap;
    gap: 12px 40px;
    margin: 22px 0 0;
    padding: 16px 0;
    border-top: 1px solid var(--q-line);
    border-bottom: 1px solid var(--q-line);
}

.asset__figure { margin: 0; }

.asset__figure dt {
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
    margin-bottom: 3px;
}

.asset__figure dd {
    margin: 0;
    font-family: var(--q-font-mono);
    font-size: 1.05rem;
    font-variant-numeric: tabular-nums;
    color: var(--q-ink);
}

.asset__figure-note {
    font-size: 0.72rem !important;
    color: var(--q-ink-faint);
    margin-top: 2px !important;
}

.asset__details { margin-top: 16px; display: grid; gap: 6px; }

.asset__detail { display: flex; gap: 12px; font-size: 0.85rem; }

.asset__detail-key {
    flex: 0 0 5.5rem;
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
    padding-top: 0.25em;
}

.asset__detail-val { color: var(--q-ink-muted); min-width: 0; }

.asset__section { margin-top: 34px; }

.asset__section-head {
    display: grid;
    grid-template-columns: auto 1fr var(--rg-money);
    align-items: baseline;
    gap: 0 10px;
    padding-bottom: 7px;
    margin-bottom: 10px;
    border-bottom: 1.5px solid color-mix(in srgb, var(--q-ink) 30%, var(--q-line));
}

.asset__section-name {
    font-family: var(--q-font-display);
    font-size: 1.02rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    color: var(--q-ink);
}

.asset__none { font-size: 0.88rem; color: var(--q-ink-muted); margin: 10px 0 0; }

.asset__year {
    display: grid;
    grid-template-columns: auto 1fr var(--rg-money);
    align-items: baseline;
    gap: 0 10px;
    margin-top: 18px;
    padding-bottom: 5px;
}

.asset__year-name {
    font-family: var(--q-font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.16em;
    color: var(--q-ink-faint);
}

.asset__entry {
    display: grid;
    grid-template-columns: 4.2rem minmax(0, 1fr) var(--rg-meter) var(--rg-money);
    align-items: center;
    gap: 0 10px;
    width: calc(100% + var(--rg-bleed) * 2);
    margin: 0 calc(var(--rg-bleed) * -1);
    padding: 9px var(--rg-bleed);
    border: none;
    border-bottom: 1px solid var(--q-line-soft);
    background: none;
    font: inherit;
    text-align: left;
    color: var(--q-ink);
    cursor: pointer;
    transition: background-color 0.12s;
    box-sizing: border-box;
}

.asset__entry:hover { background: color-mix(in srgb, var(--q-ink) 5%, transparent); }
.asset__entry:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: -2px; }

.asset__entry-date {
    font-family: var(--q-font-mono);
    font-size: 0.74rem;
    font-variant-numeric: tabular-nums;
    color: var(--q-ink-faint);
}

.asset__entry-what {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-size: 0.85rem;
    font-weight: 600;
}

/* How many photographs hang off a job, as a count rather than a paperclip —
   the app has no clip glyph and does not need one for this. */
.asset__entry-clip {
    flex-shrink: 0;
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    line-height: 1;
    padding: 2px 5px;
    border: 1px solid var(--q-line);
    border-radius: 2px;
    color: var(--q-ink-faint);
}

/* ── Off the register ───────────────────────────────────────────────────── */

/* Ochre, not vermilion: an archived asset is a state, not an alarm, and
   vermilion in this design means late and nothing else. */
.asset__archived {
    display: flex;
    align-items: center;
    gap: 14px;
    flex-wrap: wrap;
    margin-top: 18px;
    padding: 12px 14px;
    border: 1px solid color-mix(in srgb, var(--pri-medium) 32%, transparent);
    border-left: 3px solid var(--pri-medium);
    border-radius: var(--radius-sm, 4px);
    background: color-mix(in srgb, var(--pri-medium) 10%, transparent);
}

.asset__archived-text {
    flex: 1 1 16rem;
    min-width: 0;
    font-size: 0.86rem;
    color: var(--q-ink-muted);
}

.asset__archived-text strong { color: var(--q-ink); }

.asset__foot {
    display: flex;
    align-items: baseline;
    gap: 12px;
    flex-wrap: wrap;
    margin-top: 46px;
    padding-top: 14px;
    border-top: 1px solid var(--q-line-soft);
}

/* Deliberately not a .q-btn--danger: nothing is destroyed, and dressing a
   reversible act in the alarm colour teaches the reader to distrust the colour. */
.asset__retire {
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    font-size: 0.82rem;
    color: var(--q-ink-muted);
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
}

.asset__retire:hover { color: var(--q-ink); }
.asset__retire:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: 2px; }
.asset__retire:disabled { opacity: 0.5; cursor: default; }

.asset__foot-note {
    font-size: 0.76rem;
    color: var(--q-ink-faint);
}

/* ── The Reckoning — the register stood back from ───────────────────────── */

/* Drawn with the ledger's own primitives wherever one exists: .asset__figures
   for the band, .asset__section-head for the heads, .register__rule and
   .register__figure for the leaders and the figures, .asset__entry for the
   recent jobs. A column here therefore lines up with the same column on an
   asset's own page, which is the whole reason those gutters are variables.

   What is new below is only what a ledger has no shape for: twelve months as
   bars, a two-up, and a marked line.

   The bars are divs with a percentage height, deliberately, and not a chart
   library. ApexCharts renders literal SVG and cannot read a custom property, so
   /stats has to re-theme itself imperatively on every dark-mode toggle and
   re-key every chart; a div inherits this token table for free, prints, and
   adds no package. */

.review__months {
    display: grid;
    grid-template-columns: repeat(12, minmax(0, 1fr));
    gap: 6px;
    align-items: end;
    margin-top: 6px;
}

.review__month { display: grid; gap: 6px; }

.review__track {
    height: 88px;
    display: flex;
    align-items: flex-end;
    border-bottom: 1px solid var(--q-line);
}

.review__bar { width: 100%; background: color-mix(in srgb, var(--q-ink) 72%, transparent); }

/* The month in hand, in the marker — a fill, never type. See the two rules at
   the head of this sheet. */
.review__bar--now { background: var(--q-accent); }

/* Jobs were logged and not one of them carried a price. Ochre, because it is a
   caveat and not an alarm: vermilion means late and nothing else. */
.review__tick {
    width: 100%;
    height: 0;
    border-top: 2px dashed var(--pri-medium);
}

.review__month-name {
    font-family: var(--q-font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.04em;
    text-align: center;
    color: var(--q-ink-faint);
}

.review__legend {
    margin: 10px 0 0;
    font-family: var(--q-font-mono);
    font-size: 0.66rem;
    color: var(--q-ink-faint);
}

/* Folds to one column on its own, without a breakpoint: two money columns at
   less than 280px each stop being readable long before the sheet does. */
.review__two {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 0 40px;
}

.review__kicker {
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
    margin-bottom: 3px;
}

.review__kicker--second { margin-top: 20px; }

/* Named areas rather than three columns, so a row that carries a note puts it on a
   line of its own underneath. Nested inside the name instead, the note makes that
   cell two lines tall and the leader — which aligns to the end of its row — drops to
   the second line, where it reads as a rule ruled under the wrong thing. */
.review__row {
    display: grid;
    grid-template-columns: minmax(0, auto) 1fr var(--rg-money);
    grid-template-areas:
        "name rule figure"
        "note note note";
    align-items: baseline;
    gap: 0 6px;
    width: 100%;
    padding: 7px 0;
    border: none;
    border-bottom: 1px solid var(--q-line-soft);
    background: none;
    font: inherit;
    text-align: left;
    color: var(--q-ink);
    box-sizing: border-box;
}

.review__row-name {
    grid-area: name;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    font-size: 0.88rem;
}

.review__row > .register__rule { grid-area: rule; }
.review__row > .register__figure { grid-area: figure; }

.review__row-note {
    grid-area: note;
    margin-top: 2px;
    font-size: 0.72rem;
    color: var(--q-ink-faint);
}

.review__row--link {
    width: calc(100% + var(--rg-bleed) * 2);
    margin: 0 calc(var(--rg-bleed) * -1);
    padding: 7px var(--rg-bleed);
    cursor: pointer;
    transition: background-color 0.12s;
}

.review__row--link:hover { background: color-mix(in srgb, var(--q-ink) 5%, transparent); }
.review__row--link:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: -2px; }

/* Ochre down the edge, the same mark an archived asset carries. No radius: a
   corner rounded on one side only reads as a printing fault.

   Flush at the column edge rather than bled into the gutter like a ledger row,
   and that is load-bearing rather than taste. Below 1024px --rg-gutter is 0, so a
   -8px bleed puts this border outside .bs__page — which is the scroll container at
   those widths, and therefore clips it. The mark would simply not be there on a
   phone, which is the one place a row of unmarked sentences reads as a mistake.
   Flush also lines the ochre up with the section rule above it. */
.review__mark {
    display: block;
    width: 100%;
    margin: 0 0 6px;
    padding: 8px 0 8px 11px;
    border: none;
    border-left: 3px solid var(--pri-medium);
    border-radius: 0;
    background: none;
    font: inherit;
    font-size: 0.88rem;
    text-align: left;
    color: var(--q-ink);
    cursor: pointer;
    transition: background-color 0.12s;
    box-sizing: border-box;
}

.review__mark:hover { background: color-mix(in srgb, var(--q-ink) 5%, transparent); }
.review__mark:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: -2px; }

/* ── Photographs ────────────────────────────────────────────────────────── */

.photo-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 10px 0;
}

.photo-grid__cell { position: relative; margin: 0; width: 92px; height: 92px; }

.photo-grid__open {
    display: block;
    width: 100%;
    height: 100%;
    padding: 0;
    border: 1px solid var(--q-line);
    border-radius: 3px;
    background: none;
    cursor: pointer;
    overflow: hidden;
}

.photo-grid__open:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: 2px; }

.photo-grid__img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    border-radius: 2px;
}

.photo-grid__cell > .photo-grid__img {
    border: 1px solid var(--q-line);
    border-radius: 3px;
}

.photo-grid__remove {
    position: absolute;
    top: -6px;
    right: -6px;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    border: 1px solid var(--q-line);
    border-radius: 50%;
    background: var(--q-surface-raised);
    color: var(--q-ink-muted);
    cursor: pointer;
}

.photo-grid__remove:hover { color: var(--pri-high); border-color: var(--pri-high); }
.photo-grid__remove:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: 1px; }

.photo-picker { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }

/* The real <input type="file"> is kept in the layout but visually hidden, so the
   label stays a real label and the control keeps its keyboard behaviour. */
.photo-picker__input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    overflow: hidden;
}

.photo-picker__btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px dashed var(--q-line);
    border-radius: var(--radius-md, 6px);
    font-size: 0.82rem;
    color: var(--q-ink-muted);
    cursor: pointer;
}

.photo-picker__btn:hover { border-color: var(--q-accent-text); color: var(--q-ink); }
.photo-picker__btn:focus-within { outline: 2px solid var(--q-accent-text); outline-offset: 2px; }

.photo-picker__busy { font-size: 0.78rem; color: var(--q-ink-faint); }
.photo-picker__error { font-size: 0.78rem; color: var(--pri-high); }

.photo-lightbox {
    position: fixed;
    inset: 0;
    z-index: 1500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 32px;
    background: color-mix(in srgb, #16140f 82%, transparent);
    cursor: zoom-out;
}

.photo-lightbox__img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 3px;
    cursor: default;
}

.photo-lightbox__close {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 38px;
    height: 38px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--q-line);
    border-radius: 50%;
    background: var(--q-surface-raised);
    color: var(--q-ink);
    cursor: pointer;
}

/* ── The dialogs ────────────────────────────────────────────────────────── */

.reg-dialog-overlay {
    position: fixed;
    inset: 0;
    z-index: 1400;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    background: color-mix(in srgb, #16140f 55%, transparent);
    overflow-y: auto;
}

.reg-dialog {
    width: 100%;
    max-width: 520px;
    max-height: 90vh;
    overflow-y: auto;
    padding: 22px;
    border: 1px solid var(--q-line);
    border-radius: var(--radius-md, 6px);
    background: var(--q-surface-raised);
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.22);
}

.reg-dialog__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-bottom: 18px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--q-line-soft);
}

.reg-dialog__row { display: flex; gap: 12px; }
.reg-dialog__col { flex: 1 1 0; min-width: 0; }
.reg-dialog__col--narrow { flex: 0 0 5.5rem; }

.reg-dialog__footer {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 20px;
    padding-top: 16px;
    border-top: 1px solid var(--q-line-soft);
}

.reg-dialog__spacer { flex: 1; }

.reg-color-row { display: flex; align-items: center; gap: 10px; }

.reg-color-pick {
    flex-shrink: 0;
    width: 34px;
    height: 34px;
    padding: 0;
    border: 1.5px solid var(--q-line);
    border-radius: 50%;
    background: none;
    cursor: pointer;
    overflow: hidden;
}

.reg-color-pick:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: 2px; }
.reg-color-pick::-webkit-color-swatch-wrapper { padding: 0; }
.reg-color-pick::-webkit-color-swatch { border: none; border-radius: 50%; }
.reg-color-pick::-moz-color-swatch { border: none; border-radius: 50%; }

.reg-color-value { font-family: var(--q-font-mono); font-size: 0.78rem; color: var(--q-ink-faint); }

@media (max-width: 700px) {
    .register__row { grid-template-columns: 8px minmax(0, 1fr) var(--rg-money); }

    /* Below the fold the subtitle and the meter drop out rather than wrapping —
       a ledger row that becomes three lines has stopped being a row. */
    .register__lead,
    .register__figure--meter { display: none; }

    .asset__entry { grid-template-columns: 4.2rem minmax(0, 1fr) var(--rg-money); }

    /* Twelve mono labels will not fit across a phone, so every other one carries
       the strip. The bars all stay — it is the reading that thins out, not the
       year. */
    .review__months { gap: 3px; }
    .review__month:nth-child(even) .review__month-name { visibility: hidden; }

    /* The recent-jobs rows carry the asset's name as well as the job's, which the
       asset page's own history does not, so they run out of line first. The leader
       goes rather than the words: on a phone it spans 30px, which is not a gap the
       eye needs help crossing. Scoped to this page for that reason. */
    .review .asset__entry-lead .register__rule { display: none; }

    .reg-dialog__row { flex-direction: column; gap: 0; }
    .reg-dialog__col--narrow { flex: 1 1 auto; }
}

/* ── The Pro mark ─────────────────────────────────────────────────────────── */

/* The word Pro as the brand sets it: the display face, italic, on the accent well
   — the same highlight the front door draws under a phrase, made into a mark.
   Sized by its context (1em), so the folio, an eyebrow and a heading each carry it
   at their own size. The outline form is the Free reader's: the same shape, empty. */
.pro-mark {
    display: inline-block;
    font-family: var(--q-font-display);
    font-style: italic;
    font-weight: 600;
    font-size: 1em;
    line-height: 1;
    letter-spacing: 0;
    text-transform: none;
    padding: 0.1em 0.42em 0.18em 0.36em;
    border-radius: 3px;
    background: var(--q-accent);
    color: var(--q-accent-ink);
    font-variation-settings: "opsz" 24, "SOFT" 60, "WONK" 1;
    vertical-align: baseline;
}

.pro-mark--outline {
    background: transparent;
    color: var(--q-ink-muted);
    box-shadow: inset 0 0 0 1px var(--q-line);
}

/* ── The Pro gate ─────────────────────────────────────────────────────────── */

/* What a Free reader sees in place of a Pro feature. Set like the register's empty
   state — a rule, a line, a note — because it is the same kind of thing: a page with
   nothing to show yet and a plain word about why. Never a wall, never a modal. */
.pro-gate {
    /* The page column hands itself over flush, so the card carries the gutters a
       page would have set: the same measure and margins as the welcome page. */
    box-sizing: content-box;
    max-width: 52ch;
    padding: 36px 28px 48px;
}

/* Inside the settings column, which pads itself, the card sits flush with the
   heading above it and rules itself off like a section. */
.pro-gate--flush {
    margin-top: 18px;
    padding: 18px 0 8px;
    border-top: 1.5px solid var(--q-line);
}

.pro-gate__kicker {
    margin: 0 0 8px;
    font-family: var(--q-font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--q-accent-text, var(--q-ink-muted));
}

.pro-gate__line {
    font-family: var(--q-font-display);
    font-size: 1.25rem;
    font-weight: 600;
    line-height: 1.25;
    margin: 0 0 8px;
    color: var(--q-ink);
}

.pro-gate__note {
    margin: 0 0 16px;
    font-size: 0.92rem;
    line-height: 1.5;
    color: var(--q-ink-muted);
}

.pro-gate__actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

/* The list behind the card's "What Pro includes": the same five lines the plans
   page prints, opened over the page in the register's dialog frame, so a reader
   asking about the door does not have to leave the corridor. The feature they
   came for is marked with the accent down its left edge. */
.pro-dialog {
    max-width: 560px;
}

.pro-dialog__kicker {
    margin: 0;
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--q-font-mono);
    font-size: 0.62rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--q-ink-faint);
}

.pro-dialog__kicker .pro-mark {
    font-size: 0.9rem;
}

.pro-dialog__title {
    margin: 0 0 14px;
    font-family: var(--q-font-display);
    font-weight: 600;
    font-size: 1.5rem;
    line-height: 1.15;
    letter-spacing: -0.01em;
    color: var(--q-ink);
    font-variation-settings: "opsz" 48, "SOFT" 30;
}

.pro-dialog__list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.pro-dialog__item {
    padding: 10px 0 10px 14px;
    border-top: 1px solid var(--q-line-soft);
    border-left: 3px solid transparent;
}

.pro-dialog__item--here {
    border-left-color: var(--q-accent);
}

.pro-dialog__name {
    margin: 0 0 2px;
    font-size: 0.9rem;
    font-weight: 600;
    color: var(--q-ink);
}

.pro-dialog__here {
    margin-left: 8px;
    font-family: var(--q-font-mono);
    font-size: 0.6rem;
    font-weight: 500;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--q-accent-text, var(--q-ink-muted));
}

.pro-dialog__line {
    margin: 0;
    font-size: 0.84rem;
    line-height: 1.45;
    color: var(--q-ink-muted);
}

.pro-dialog__fine {
    margin: 14px 0 0;
    font-size: 0.82rem;
    line-height: 1.5;
    color: var(--q-ink-faint);
}

/* Public pages: lavender canvas, rounded surfaces, and Daybook's own screens.
   NewsstandSheet puts `daybook-public` on every signed-out page, so the front
   page, the sign-in pages and the notices all wear the same look; the rules below
   restyle the newsstand base above rather than replace it. The restrained palette
   leaves chartreuse as the recognizable daybreak accent. */
.daybook-public {
    background: var(--q-bg);
    padding-top: max(24px, env(safe-area-inset-top));
    padding-bottom: max(24px, env(safe-area-inset-bottom));
}
.daybook-public .newsstand__sheet { max-width: 1120px; }
.daybook-public .newsstand__mast { display: flex; align-items: center; justify-content: flex-start; gap: 10px; padding: 8px 0 24px; text-align: left; }
.daybook-public .newsstand__mark-well { margin: 0; }
.daybook-public .daybreak { width: 48px; height: 40px; }
.daybook-public .newsstand__wordmark { font-size: 2rem; text-shadow: none; }
.daybook-public .newsstand__creed, .daybook-public .newsstand__rule { display: none; }
.daybook-public a:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: 4px; }

/* Two columns: the introduction, and the form on its card. */
.daybook-public .newsstand__cols { grid-template-columns: minmax(0, 1fr) 400px; gap: 64px; margin-top: 40px; align-items: start; }
.daybook-public .newsstand__leader { padding: 0; border: 0; }
.daybook-public .newsstand__coupon-well { padding: 0; }
.login__headline { margin: 0; font-family: var(--q-font-display); font-weight: 500; font-size: clamp(2.5rem, 4.7vw, 4.1rem); letter-spacing: -.045em; line-height: 1.07; }
.login__intro { max-width: 42ch; margin: 20px 0 28px; color: var(--q-ink-muted); font-size: 1rem; line-height: 1.7; }
.login__store { display: inline-flex; align-items: center; min-height: 44px; font-size: .85rem; color: var(--q-accent-text); }
.daybook-public .newsstand__head { margin: 0 0 20px; font-weight: 500; font-size: clamp(2.3rem, 4.2vw, 3.5rem); letter-spacing: -.045em; line-height: 1.07; text-shadow: none; }
.daybook-public .newsstand__lead { max-width: 46ch; font-size: 1rem; line-height: 1.7; }
/* Steps, numbered in the lavender well. */
.daybook-public .newsstand__notice-list { counter-reset: db-step; gap: 14px; margin-top: 28px; padding: 0; border: 0; font-size: .9rem; }
.daybook-public .newsstand__notice-list li { counter-increment: db-step; min-height: 28px; padding-left: 42px; padding-top: 3px; }
.daybook-public .newsstand__notice-list li::before { content: counter(db-step); top: 0; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background: var(--q-well); color: var(--q-well-ink); font: 600 .75rem var(--q-font-body); }

/* The form card and its fields: boxes with soft corners, labels in the body face. */
.daybook-public .newsstand__coupon { padding: 30px; border-color: transparent; border-radius: 24px; box-shadow: none; }
.daybook-public .newsstand__coupon-title { margin-bottom: 22px; font-size: 1.9rem; line-height: 1.1; }
.login__form-intro { margin: -12px 0 26px; color: var(--q-ink-muted); font-size: .85rem; line-height: 1.5; }
.daybook-public .newsstand__label { margin-bottom: 6px; font-family: var(--q-font-body); font-size: .8rem; letter-spacing: 0; text-transform: none; color: var(--q-ink-muted); }
.daybook-public .newsstand__label-row .newsstand__label { margin-bottom: 0; }
.daybook-public .newsstand__label-link { display: inline-flex; align-items: center; min-height: 44px; font-family: var(--q-font-body); font-size: .75rem; letter-spacing: 0; text-transform: none; }
.daybook-public .newsstand__input { min-height: 52px; padding: 12px 14px; border: 1px solid var(--q-line); border-radius: 12px; background: var(--q-surface); font-size: 16px; }
.daybook-public .newsstand__input:focus { border-color: var(--q-accent-text); box-shadow: 0 0 0 3px color-mix(in srgb, var(--q-accent) 45%, transparent); }
.daybook-public .newsstand__input.invalid { border-color: var(--pri-high); }
.daybook-public .newsstand__input:-webkit-autofill { -webkit-box-shadow: inset 0 0 0 100px var(--q-surface); }
.daybook-public .newsstand__erratum { padding: 12px 14px; border-left: 0; border-radius: 12px; }
.daybook-public .newsstand__keep { min-height: 44px; margin: 12px 0; }
.daybook-public .newsstand__check { width: 18px; height: 18px; border-radius: 5px; }
.daybook-public .newsstand__note { margin: 4px 0 20px; color: var(--q-ink-muted); }
.daybook-public .newsstand__or { font-family: var(--q-font-body); font-size: .75rem; letter-spacing: 0; text-transform: none; }
.daybook-public .newsstand__stamp { background: var(--q-ink); color: var(--q-surface-raised); border-color: var(--q-ink); }
.daybook-public .newsstand__stamp:hover { background: var(--q-ink-muted); box-shadow: none; }
.daybook-public .newsstand__stamp, .daybook-public .newsstand__alt { min-height: 52px; border-radius: 999px; font-family: var(--q-font-body); font-size: .9rem; letter-spacing: 0; text-indent: 0; text-transform: none; }
.daybook-public .newsstand__alt { color: var(--q-ink); }
.daybook-public .newsstand__subscribe { margin-top: 14px; font-size: .85rem; }
.daybook-public .newsstand__subscribe a, .login__signup a { display: inline-block; padding: 12px 2px; color: var(--q-ink); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.login__password { display: block; position: relative; }
.daybook-public .login__password .newsstand__input { padding-right: 70px; }
.login__reveal { position: absolute; top: 4px; right: 4px; min-width: 60px; min-height: 44px; background: transparent; border: 0; border-radius: 8px; color: var(--q-ink); font: 600 .8rem var(--q-font-body); cursor: pointer; }
/* Cloudflare's check, its height held from the first paint so Sign in does not jump when it draws. */
.login__turnstile { display: block; min-height: 65px; margin: 0 0 16px; }
.login__reveal[hidden] { display: none; }
.login__reveal:focus-visible { outline: 2px solid var(--q-accent-text); }
.login__signup { padding: 14px 8px 0; text-align: center; }
.login__signup p { margin: 6px 0; color: var(--q-ink-muted); font-size: .8rem; line-height: 1.6; }
.login__signup .login__trial { font-size: .75rem; }

/* One measure to be read: Privacy, Terms, Support, Pricing and the short notices,
   set on a single rounded card. */
.daybook-public .newsstand__page { margin-top: 16px; }
.daybook-public .notice { max-width: 760px; box-sizing: border-box; padding: clamp(28px, 5vw, 56px); border-radius: 28px; background: var(--q-surface-raised); }
.daybook-public .notice__title { margin: 0 0 14px; font-weight: 500; font-size: clamp(2.3rem, 5vw, 3.4rem); letter-spacing: -.045em; line-height: 1.05; text-shadow: none; }
.daybook-public .notice__dateline { display: inline-block; margin: 0 0 20px; padding: 5px 12px; border-radius: 999px; background: var(--q-well); color: var(--q-well-ink); font: 500 .75rem var(--q-font-body); letter-spacing: 0; text-transform: none; }
.daybook-public .notice__lede { font-size: 1.05rem; line-height: 1.7; }
.daybook-public .notice h3 { margin: 36px 0 10px; padding: 0; border: 0; font-weight: 500; font-size: 1.45rem; letter-spacing: -.02em; }
.daybook-public .notice a { color: var(--q-ink); text-decoration: underline; text-decoration-color: color-mix(in srgb, var(--q-accent-text) 55%, transparent); text-underline-offset: 3px; }
.daybook-public .notice a:hover { text-decoration-color: currentColor; }
.daybook-public .notice .newsstand__subscribe { text-align: left; margin-top: 24px; }
.daybook-public .notice .newsstand__stamp { width: fit-content; padding: 0 28px; display: inline-flex; align-items: center; color: var(--q-surface-raised); text-decoration: none; }

/* The footer: the same links, in the body face. */
.daybook-public .newsstand__colophon { margin-top: 32px; gap: 4px 22px; border-top-color: var(--q-line); font-family: var(--q-font-body); font-size: .8rem; letter-spacing: 0; text-transform: none; }
.daybook-public .newsstand__colophon a { display: inline-flex; align-items: center; min-height: 44px; color: var(--q-ink-muted); }

/* The front page. */
.daybook-home .newsstand__cols { grid-template-columns: 1fr 1fr; align-items: center; gap: 48px; margin-top: 28px; }
.daybook-home .front__fine { color: var(--q-ink-muted); line-height: 1.6; }
.daybook-benefits { display: grid; grid-template-columns: repeat(3, 1fr); gap: 32px; padding: 64px 0 48px; }
.daybook-benefits__symbol { display: grid; place-items: center; width: 46px; height: 46px; border-radius: 15px; background: var(--q-well); color: var(--q-well-ink); font-size: 1.5rem; }
.daybook-benefits h3 { font: 500 1.5rem var(--q-font-display); margin: 18px 0 12px; }
.daybook-benefits p, .daybook-pro p { color: var(--q-ink-muted); font-size: .9rem; line-height: 1.7; max-width: 48ch; }
.daybook-pro { display: flex; align-items: center; justify-content: space-between; gap: 24px; background: var(--q-well); padding: 32px; border-radius: 28px; }
.daybook-pro h2 { font: 500 2rem var(--q-font-display); margin: 0 0 16px; }
.daybook-pro a { flex-shrink: 0; }

/* Pricing: the two plans side by side, then the three ways to pay. */
.daybook-public .plans { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin: 28px 0 8px; }
.plans__card { padding: 24px; border-radius: 20px; background: var(--q-surface); border: 1px solid var(--q-line-soft); }
.plans__card--pro { background: color-mix(in srgb, var(--q-accent) 16%, var(--q-surface-raised)); border-color: color-mix(in srgb, var(--q-accent) 55%, transparent); }
.daybook-public .plans__card h3 { margin: 0 0 6px; font-size: 1.6rem; }
.daybook-public .plans__price { margin: 0 0 14px; font-size: .85rem; }
.daybook-public .plans__card ul { margin: 0; padding: 0; list-style: none; }
.daybook-public .plans__card li { position: relative; margin: 0 0 8px; padding-left: 26px; font-size: .9rem; }
.plans__card li::before { content: ""; position: absolute; left: 0; top: .3em; width: 16px; height: 16px; border-radius: 50%; background: var(--q-accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2316140f' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 10px no-repeat; }
.daybook-public .offers { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin: 14px 0 20px; padding: 0; list-style: none; }
.daybook-public .offers li { display: flex; flex-direction: column; gap: 4px; margin: 0; padding: 18px; border-radius: 18px; background: var(--q-surface); border: 1px solid var(--q-line-soft); font-size: .85rem; line-height: 1.5; }
.offers__name { color: var(--q-ink); font-weight: 600; }
.offers__price { font: 500 2rem/1.1 var(--q-font-display); letter-spacing: -.03em; color: var(--q-ink); }
.offers__price small { font: 400 .8rem var(--q-font-body); letter-spacing: 0; color: var(--q-ink-muted); }

:root[data-public-theme="dark"] .daybook-public .notice .newsstand__stamp { color: var(--q-bg); }
    :root[data-public-theme="dark"] .plans__card--pro { background: color-mix(in srgb, var(--q-accent) 10%, var(--q-surface)); }
@media (prefers-color-scheme: dark) {:root:not([data-public-theme="light"]):not([data-public-theme="dark"]) .daybook-public .notice .newsstand__stamp { color: var(--q-bg); }
    :root:not([data-public-theme="light"]):not([data-public-theme="dark"]) .plans__card--pro { background: color-mix(in srgb, var(--q-accent) 10%, var(--q-surface)); }
}
@media (max-width: 899.98px) {
    .daybook-public .newsstand__sheet { max-width: 560px; }
    .daybook-public .newsstand__cols { gap: 32px; margin-top: 24px; align-items: stretch; }
    .daybook-public .newsstand__mast { justify-content: center; padding-bottom: 20px; }
    .daybook-public .login__headline { font-size: clamp(2.35rem, 7vw, 3.4rem); }
    /* Form first, then the introduction under a hairline. The front page leads instead. */
    .daybook-public:not(.newsstand--front) .newsstand__leader { padding-top: 28px; border-top: 1px solid var(--q-line); }
    .daybook-public .newsstand__coupon { padding: 24px; }
    .daybook-benefits { grid-template-columns: 1fr; gap: 28px; padding: 40px 0; }
    .daybook-pro { flex-direction: column; align-items: flex-start; padding: 24px; }
}
@media (max-width: 599.98px) {
    .daybook-public .plans, .daybook-public .offers { grid-template-columns: minmax(0, 1fr); }
    .daybook-public .notice { border-radius: 24px; }
}
@media (max-width: 399.98px) {
    .daybook-public { padding-left: max(16px, env(safe-area-inset-left)); padding-right: max(16px, env(safe-area-inset-right)); }
    .daybook-public .newsstand__coupon { padding: 22px 16px; }
    .daybook-public .notice { padding: 26px 18px; }
}

/* The iPhone app, shown with real captures in drawn handsets fanned across a soft
   stage: the middle screen stands forward, its neighbours sit lower and behind. */
.iphone-preview { max-width: 560px; margin: 0 auto; }
.iphone-preview__heading { display: flex; align-items: center; flex-wrap: wrap; gap: 10px 14px; }
.iphone-preview__heading h3 { margin: 0; font: 500 1.65rem var(--q-font-display); letter-spacing: -.02em; }
.iphone-preview__heading > span { padding: 5px 11px; border-radius: 999px; background: var(--q-accent); color: var(--q-accent-ink); font-size: .7rem; font-weight: 600; }
.iphone-preview__intro { margin: 12px 0 0; max-width: 46ch; color: var(--q-ink-muted); font-size: .88rem; line-height: 1.6; }
.iphone-stage {
    position: relative; display: flex; justify-content: center; align-items: flex-start;
    margin: 22px 0 0; padding: clamp(28px, 5vw, 44px) 4% 0; overflow: hidden; border-radius: 32px;
    background:
        radial-gradient(58% 46% at 50% 30%, color-mix(in srgb, var(--q-accent) 42%, transparent), transparent 72%),
        linear-gradient(180deg, color-mix(in srgb, var(--q-surface-raised) 70%, var(--q-bg)), color-mix(in srgb, #b9addf 40%, var(--q-bg)));
}
/* Phones run off the bottom of the stage, the way they rest in a hand. */
.iphone { position: relative; flex: 0 0 37%; min-width: 0; margin: 0 0 -14%; }
.iphone--calendar, .iphone--focus { flex-basis: 31%; margin-top: 9%; z-index: 0; }
.iphone--calendar { margin-right: -7%; }
.iphone--focus { margin-left: -7%; }
.iphone--today { z-index: 1; }
.iphone__frame {
    display: block; padding: 3.2%; border-radius: 17% / 7.8%; background: #1b1824;
    box-shadow: inset 0 0 0 1.5px #57506a, inset 0 0 0 3px #1b1824, 0 28px 50px -18px rgb(28 22 48 / 45%);
    transition: transform .25s ease;
}
.iphone--calendar .iphone__frame, .iphone--focus .iphone__frame { box-shadow: inset 0 0 0 1.5px #57506a, inset 0 0 0 3px #1b1824, 0 18px 36px -16px rgb(28 22 48 / 35%); }
.iphone__frame:hover { transform: translateY(-6px); }
.iphone__frame:focus-visible { outline: 3px solid var(--q-accent-text); outline-offset: 4px; }
.iphone__screen { position: relative; display: block; overflow: hidden; border-radius: 14% / 6.4%; background: #f1ede4; }
/* The Dynamic Island, drawn over the status bar's empty middle. */
.iphone__screen::after { content: ""; position: absolute; top: 1.25%; left: 34.5%; width: 31%; height: 4.2%; border-radius: 999px; background: #000; }
.iphone__screen img { display: block; width: 100%; height: auto; }
.iphone-preview__features { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; margin: 18px 0 0; padding: 0; list-style: none; text-align: center; }
.iphone-preview__features li { display: flex; flex-direction: column; gap: 3px; font-size: .75rem; line-height: 1.45; color: var(--q-ink-muted); }
.iphone-preview__features strong { color: var(--q-ink); font-size: .8rem; font-weight: 600; }
.iphone-preview__availability { font-size: .8rem; line-height: 1.5; color: var(--q-ink-muted); text-align: center; margin: 18px 0 0; }
.iphone-preview > .front__stamp { display: flex; width: fit-content; margin: 20px auto 0; }
.daybook-public .newsstand__leader .iphone-preview { margin: 32px 0 0; max-width: none; }
:root[data-public-theme="dark"] .iphone-stage { background:
        radial-gradient(58% 46% at 50% 30%, color-mix(in srgb, var(--q-accent) 22%, transparent), transparent 72%),
        linear-gradient(180deg, var(--q-surface), color-mix(in srgb, #6c5c9c 30%, var(--q-bg))); }
    :root[data-public-theme="dark"] .iphone__frame, :root[data-public-theme="dark"] .iphone--calendar .iphone__frame, :root[data-public-theme="dark"] .iphone--focus .iphone__frame { box-shadow: inset 0 0 0 1.5px #6f6886, inset 0 0 0 3px #1b1824, 0 24px 44px -18px rgb(0 0 0 / 60%); }
@media (prefers-color-scheme: dark) {:root:not([data-public-theme="light"]):not([data-public-theme="dark"]) .iphone-stage { background:
        radial-gradient(58% 46% at 50% 30%, color-mix(in srgb, var(--q-accent) 22%, transparent), transparent 72%),
        linear-gradient(180deg, var(--q-surface), color-mix(in srgb, #6c5c9c 30%, var(--q-bg))); }
    :root:not([data-public-theme="light"]):not([data-public-theme="dark"]) .iphone__frame, :root:not([data-public-theme="light"]):not([data-public-theme="dark"]) .iphone--calendar .iphone__frame, :root:not([data-public-theme="light"]):not([data-public-theme="dark"]) .iphone--focus .iphone__frame { box-shadow: inset 0 0 0 1.5px #6f6886, inset 0 0 0 3px #1b1824, 0 24px 44px -18px rgb(0 0 0 / 60%); }
}
@media (prefers-reduced-motion: reduce) {
    .iphone__frame { transition: none; }
    .iphone__frame:hover { transform: none; }
}
@media (max-width: 479.98px) {
    .iphone-stage { border-radius: 24px; padding-left: 2%; padding-right: 2%; }
    .iphone { flex-basis: 42%; }
    .iphone--calendar, .iphone--focus { flex-basis: 34%; }
    .iphone--calendar { margin-right: -10%; }
    .iphone--focus { margin-left: -10%; }
    .iphone__frame { padding: 2.8%; }
    .iphone-preview__features { gap: 8px; }
    .iphone-preview__features li { font-size: .7rem; }
}

/* The website, shown with real captures: Today in a drawn browser window at the
   full measure, then close-ups of Calendar, Habits and Countdowns in a row, which
   becomes a strip to swipe once the sheet narrows to one column. */
.web-preview { padding: 88px 0; border-top: 1px solid var(--q-line-soft); scroll-margin-top: 24px; }
.web-preview .product-section-heading { margin-bottom: 40px; }
.web-window, .web-shot { margin: 0; }
.web-window__frame, .web-shot__frame {
    display: block; overflow: hidden; background: var(--q-surface-raised);
    box-shadow: 0 0 0 1px var(--q-line-soft), 0 26px 52px -30px rgb(28 22 48 / 42%);
    transition: transform .25s ease;
}
.web-window__frame { border-radius: 18px; }
.web-shot__frame { border-radius: 16px; }
.web-window__frame:hover, .web-shot__frame:hover { transform: translateY(-4px); }
.web-window__bar {
    display: grid; grid-template-columns: 1fr minmax(0, auto) 1fr; align-items: center; gap: 12px;
    padding: 10px 16px; border-bottom: 1px solid var(--q-line-soft); background: var(--q-surface);
}
.web-window__dots { display: flex; gap: 7px; }
.web-window__dots i { width: 11px; height: 11px; border-radius: 50%; background: var(--q-line); }
.web-window__address {
    overflow: hidden; padding: 5px 22px; border-radius: 999px; background: var(--q-bg);
    color: var(--q-ink-muted); font-size: .72rem; white-space: nowrap; text-overflow: ellipsis;
}
.web-window img, .web-shot img { display: block; width: 100%; height: auto; }
.web-shots { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; margin: 32px 0 0; padding: 0; list-style: none; }
.web-window figcaption, .web-shot figcaption { display: flex; flex-direction: column; gap: 3px; margin-top: 14px; font-size: .8rem; line-height: 1.5; color: var(--q-ink-muted); }
.web-window figcaption strong, .web-shot figcaption strong { color: var(--q-ink); font-size: .85rem; font-weight: 600; }
:root[data-public-theme="dark"] .web-window__frame, :root[data-public-theme="dark"] .web-shot__frame { box-shadow: 0 0 0 1px var(--q-line), 0 26px 52px -30px rgb(0 0 0 / 65%); }
@media (prefers-color-scheme: dark) {:root:not([data-public-theme="light"]):not([data-public-theme="dark"]) .web-window__frame, :root:not([data-public-theme="light"]):not([data-public-theme="dark"]) .web-shot__frame { box-shadow: 0 0 0 1px var(--q-line), 0 26px 52px -30px rgb(0 0 0 / 65%); }
}
@media (prefers-reduced-motion: reduce) {
    .web-window__frame, .web-shot__frame { transition: none; }
    .web-window__frame:hover, .web-shot__frame:hover { transform: none; }
}
@media (max-width: 899.98px) {
    .web-preview { padding: 56px 0; }
    .web-preview .product-section-heading { margin-bottom: 32px; }
    /* Room under the strip for the frames' shadows, which the scroller would clip. */
    .web-shots {
        grid-template-columns: none; grid-auto-flow: column; grid-auto-columns: 78%; gap: 14px;
        margin-top: 28px; padding: 2px 2px 22px; overflow-x: auto; overscroll-behavior-x: contain;
        scroll-snap-type: x mandatory; scrollbar-width: none;
    }
    .web-shots::-webkit-scrollbar { display: none; }
    .web-shots > li { scroll-snap-align: start; }
}
@media (max-width: 479.98px) {
    .web-window__frame { border-radius: 12px; }
    .web-window__bar { gap: 8px; padding: 7px 10px; }
    .web-window__dots { gap: 5px; }
    .web-window__dots i { width: 8px; height: 8px; }
    .web-window__address { padding: 3px 12px; font-size: .62rem; }
    .web-shots { grid-auto-columns: 84%; }
}

/* Public product navigation and buying journey. Uses Daybook's existing
   Public Sans / Fraunces pairing and lavender, plum, white and daybreak tokens. */
.daybook-public .newsstand__mast { flex-wrap: wrap; gap: 10px; padding-bottom: 20px; border-bottom: 1px solid var(--q-line); }
.daybook-public .newsstand__wordmark { color: var(--q-ink); text-decoration: none; }
.public-nav { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 22px; margin-left: auto; font-size: .85rem; }
.public-nav a { display: inline-flex; align-items: center; justify-content: center; min-height: 44px; color: var(--q-ink); text-decoration: none; }
.public-nav a:hover { text-decoration: underline; text-underline-offset: 5px; }
.public-nav .public-nav__login { border-left: 1px solid var(--q-line); padding-left: 22px; font-weight: 600; }
.public-nav .public-nav__start { padding: 0 20px; border-radius: 999px; background: var(--q-ink); color: var(--q-surface-raised); font-weight: 600; }
.daybook-public a:focus-visible, .product-questions summary:focus-visible { outline: 3px solid var(--q-accent-text); outline-offset: 5px; }
.daybook-home .login__headline { font-size: clamp(2.8rem, 5.1vw, 4.7rem); line-height: 1.07; letter-spacing: -.055em; }
.daybook-home .newsstand__cols { padding: 32px 0 40px; }
.login-benefits { list-style: none; padding: 0; margin: 22px 0 12px; color: var(--q-ink-muted); font-size: .9rem; line-height: 1.7; }
.login-benefits li { margin: 10px 0; padding-left: 25px; position: relative; }
.login-benefits li::before { content: '✓'; position: absolute; left: 0; color: var(--q-accent-text); }
.login-product-link { display: inline-block; padding: 10px 0; color: var(--q-ink); text-underline-offset: 4px; }
.product-benefits, .product-plans, .product-faq { padding: 72px 0; border-top: 1px solid var(--q-line); scroll-margin-top: 24px; }
.product-section-heading { display: grid; grid-template-columns: 1.2fr 1fr; align-items: start; gap: 60px; margin-bottom: 36px; }
.product-section-heading h2, .product-faq h2, .product-closing h2 { margin: 0; font: 500 clamp(1.9rem, 3.2vw, 2.7rem)/1.17 var(--q-font-display); letter-spacing: -.035em; }
.product-section-heading p, .product-faq p, .product-closing p { margin: 8px 0 0; color: var(--q-ink-muted); line-height: 1.75; font-size: .95rem; max-width: 60ch; }
.product-benefit-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 40px; }
.product-benefit-grid article > span { display: grid; place-items: center; width: 42px; height: 42px; background: var(--q-well); border-radius: 12px; font-size: 1.5rem; }
.product-benefit-grid h3 { font: 600 1.15rem var(--q-font-body); margin: 20px 0 12px; }
.product-benefit-grid p { color: var(--q-ink-muted); line-height: 1.75; font-size: .9rem; }
.product-benefit-grid .product-example { font-size: .8rem; border-left: 2px solid var(--q-accent-text); padding-left: 14px; margin-top: 24px; }
.product-plan-layout { display: grid; grid-template-columns: 1fr 1.6fr; gap: 24px; }
.product-free, .product-pro { padding: 32px; border: 1px solid var(--q-line); border-radius: 20px; }
.product-free { background: var(--q-surface); }
.product-pro { background: var(--q-surface-raised); }
.product-plan-layout h3 { margin: 0; font: 500 1.7rem var(--q-font-display); }
.product-price { font: 500 3rem var(--q-font-body); margin: 22px 0; }
.product-price small { font: 400 .8rem var(--q-font-body); color: var(--q-ink-muted); }
.product-plan-layout ul { padding-left: 20px; margin: 24px 0; }
.product-plan-layout li { padding-left: 4px; margin: 12px 0; font-size: .9rem; line-height: 1.55; }
.product-plan-layout a, .product-faq a, .product-trust a { color: var(--q-ink); text-underline-offset: 4px; }
.product-pro-heading span { display: block; margin-top: 8px; color: var(--q-ink-muted); font-size: .85rem; }
.product-offers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; border-top: 1px solid var(--q-line); padding-top: 24px; margin-bottom: 24px; }
.product-offers strong { font-size: 2rem; font-weight: 500; }
.product-offers span, .product-offers small { display: block; color: var(--q-ink-muted); font-size: .8rem; line-height: 1.8; }
.product-pro .newsstand__stamp, .product-closing .newsstand__stamp { display: inline-flex; align-items: center; justify-content: center; padding: 0 28px; text-decoration: none; color: var(--q-surface-raised); width: auto; }
.product-plan-note { color: var(--q-ink-muted); font-size: .75rem; line-height: 1.7; margin: 16px 0 0; }
.product-faq { display: grid; grid-template-columns: 1fr 1.5fr; gap: 70px; }
.product-faq h2 { max-width: 15ch; }
.product-questions details { border-bottom: 1px solid var(--q-line); }
.product-questions summary { cursor: pointer; padding: 20px 24px 20px 0; font-weight: 600; font-size: .95rem; line-height: 1.5; }
.product-questions details:first-child summary { padding-top: 0; }
.product-questions details p { margin: 0 0 22px; font-size: .9rem; }
.product-closing { display: flex; align-items: center; justify-content: space-between; gap: 28px; padding: 40px; background: var(--q-well); border-radius: 24px; }
.product-closing .newsstand__stamp { flex-shrink: 0; }
.product-trust { padding: 22px 0 0; text-align: center; color: var(--q-ink-muted); font-size: .75rem; line-height: 1.7; }
.product-trust a { display: inline-flex; align-items: center; min-height: 44px; margin: 0 10px; }
@media (max-width: 899.98px) {
    .daybook-public .newsstand__mast { justify-content: flex-start; }
    .public-nav { width: 100%; margin: 8px 0 0; justify-content: space-between; gap: 6px 12px; }
    .public-nav .public-nav__login { border: 0; padding-left: 0; }
    .product-section-heading, .product-benefit-grid, .product-plan-layout, .product-faq { grid-template-columns: 1fr; gap: 28px; }
    .product-benefits, .product-plans, .product-faq { padding: 44px 0; }
    .product-faq h2 { max-width: 100%; }
    .product-closing { align-items: flex-start; flex-direction: column; padding: 28px; }
    .daybook-home .newsstand__cols { padding: 16px 0 28px; }
}
@media (max-width: 399.98px) {
    .public-nav { font-size: .75rem; gap: 4px 9px; }
    .public-nav .public-nav__start { padding: 0 12px; }
    .product-free, .product-pro { padding: 24px 20px; }
}
.daybook-public .newsstand__below { padding-top: 0; border-top: 0; animation: none; }

/* The public sheet owns scrolling, so the menu sticks inside that scrollport. */
.daybook-public .newsstand__mast {
    position: sticky;
    top: -1px;
    z-index: 20;
    padding-top: max(14px, env(safe-area-inset-top));
    background: var(--q-bg);
    background: color-mix(in srgb, var(--q-bg) 94%, transparent);
    backdrop-filter: blur(18px);
    -webkit-backdrop-filter: blur(18px);
}
.daybook-public { scroll-padding-top: 110px; }
product-reveal { display: block; }
@media (max-width: 899.98px) {
    .daybook-public { scroll-padding-top: 170px; }
}
@media (prefers-reduced-motion: no-preference) {
    .daybook-public { scroll-behavior: smooth; }
}
.daybook-public { padding-top: 0; }
.daybook-public .newsstand__sheet { margin-top: 0; }
.daybook-public .newsstand__mast { top: 0; }

/* Finish the public page: quieter chrome, clear plan choices, and consistent rhythm. */
.daybook-public .newsstand__mast {
    min-height: 76px;
    padding: 12px 0;
    gap: 8px;
    border-bottom-color: var(--q-line-soft);
}
.daybook-public .newsstand__mark-well,
.daybook-public .newsstand__wordmark,
.daybook-public .newsstand__leader,
.daybook-public .newsstand__coupon-well { animation: none; }
.daybook-public .newsstand__wordmark { font-size: 1.8rem; }
.daybook-public .daybreak { width: 40px; height: 34px; }
.public-nav { gap: 6px 26px; font-size: .82rem; }
.public-nav a { text-underline-offset: 7px; }
.public-nav a.active { text-decoration: underline; text-decoration-thickness: 2px; }
.public-nav .public-nav__start { min-height: 42px; }
.daybook-home .newsstand__cols { margin-top: 24px; padding: 40px 0 56px; gap: 56px; }
.daybook-home .login__headline { font-size: clamp(2.9rem, 4.8vw, 4.4rem); line-height: 1.09; letter-spacing: -.045em; text-wrap: balance; }
.daybook-home .login__intro { max-width: 37ch; font-size: 1.08rem; line-height: 1.75; margin: 24px 0 30px; }
.daybook-home .front__actions { gap: 12px; }
.daybook-home .front__fine { font-size: .78rem; margin-top: 16px; }
.daybook-home .front__fine + .front__fine { margin-top: 4px; }
.daybook-public .newsstand__stamp { font-weight: 600; }
.daybook-home .iphone-preview__heading { gap: 8px 12px; }
.daybook-home .iphone-preview__heading h3 { font-size: 1.4rem; }
.daybook-home .iphone-preview__intro { font-size: .82rem; max-width: 44ch; }
.daybook-home .iphone-stage { border: 1px solid var(--q-line-soft); border-radius: 28px; }
.daybook-home .iphone-preview__features { margin-top: 20px; }
.daybook-home .iphone-preview__availability { font-size: .73rem; margin-top: 14px; }
.product-benefits, .product-plans, .product-faq { padding: 88px 0; border-top-color: var(--q-line-soft); }
.product-section-heading { gap: 72px; margin-bottom: 44px; }
.product-section-heading h2, .product-faq h2, .product-closing h2 { text-wrap: balance; font-size: clamp(1.9rem, 3vw, 2.6rem); }
.product-section-heading p { margin-top: 4px; font-size: .92rem; }
.product-benefit-grid { gap: 44px; }
.product-benefit-grid article > span { width: 48px; height: 48px; border-radius: 16px; color: var(--q-ink); }
.product-benefit-grid h3 { margin-top: 22px; letter-spacing: -.02em; }
.product-benefit-grid .product-example { margin-top: 20px; line-height: 1.65; }
.product-plan-layout { grid-template-columns: 1fr 1.45fr; gap: 22px; align-items: stretch; }
.product-free, .product-pro { padding: 36px; border-radius: 24px; }
.product-free { display: flex; flex-direction: column; background: transparent; border-color: var(--q-line-soft); }
.product-free > a { margin-top: auto; display: inline-flex; align-items: center; justify-content: center; min-height: 50px; border: 1px solid var(--q-line); border-radius: 999px; text-decoration: none; font-size: .85rem; font-weight: 600; }
.product-pro { border-color: color-mix(in srgb, var(--q-accent-text) 38%, var(--q-line-soft)); box-shadow: 0 12px 32px -24px rgb(0 0 0 / 30%); }
.product-price { margin: 24px 0 8px; letter-spacing: -.055em; }
.product-price small { letter-spacing: 0; }
.product-plan-layout ul { list-style: none; padding: 0; }
.product-plan-layout li { position: relative; padding-left: 25px; font-size: .85rem; }
.product-plan-layout li::before { content: '✓'; position: absolute; left: 0; color: var(--q-accent-text); font-weight: 600; }
.product-offers { gap: 8px; padding-top: 22px; }
.product-offer { padding: 16px 12px; border-radius: 14px; background: var(--q-surface); }
.product-offer--yearly { background: var(--q-well); box-shadow: inset 0 0 0 1px var(--q-line); }
.product-offers small { color: var(--q-ink); font-size: .73rem; margin-bottom: 12px; }
.product-offers strong { display: block; font-size: 2rem; line-height: 1.2; letter-spacing: -.05em; }
.product-offers span { font-size: .74rem; margin-top: 4px; }
.product-pro .newsstand__stamp { width: 100%; }
.product-plan-note { font-size: .72rem; line-height: 1.8; }
.product-faq { gap: 80px; }
.product-faq > div:first-child p { margin-top: 20px; font-size: .85rem; }
.product-questions details { border-color: var(--q-line-soft); }
.product-questions summary { position: relative; padding: 24px 38px 24px 0; list-style: none; font-size: .9rem; font-weight: 500; }
.product-questions summary::-webkit-details-marker { display: none; }
.product-questions summary::after { content: '+'; position: absolute; right: 4px; top: 50%; transform: translateY(-50%); color: var(--q-ink-muted); font-size: 1.4rem; font-weight: 400; }
.product-questions details[open] summary::after { content: '−'; }
.product-questions details:first-child summary { padding-top: 24px; }
.product-questions details[open] summary { color: var(--q-accent-text); }
.product-questions details p { padding-right: 32px; line-height: 1.8; }
.product-closing { padding: 48px; border-radius: 28px; }
.product-closing p { margin-top: 14px; font-size: .9rem; }
.product-trust { padding-top: 18px; }
.daybook-public .newsstand__colophon { justify-content: flex-start; gap: 2px 26px; padding-top: 20px; margin-top: 36px; border-top-color: var(--q-line-soft); font-size: .75rem; }
.daybook-public .newsstand__colophon > a:first-child { margin-right: auto; font: 600 1.2rem var(--q-font-display); color: var(--q-ink); }
@media (max-width: 899.98px) {
    .daybook-public .newsstand__mast { min-height: 0; padding: 12px 0 8px; }
    .daybook-public .newsstand__wordmark { font-size: 1.55rem; }
    .daybook-public .daybreak { width: 34px; height: 28px; }
    .public-nav { margin-top: 2px; gap: 4px 12px; font-size: .78rem; }
    .public-nav .public-nav__start { min-height: 40px; }
    .daybook-public { scroll-padding-top: 140px; }
    .daybook-home .newsstand__cols { padding: 24px 0 32px; gap: 40px; }
    .daybook-home .login__headline { font-size: clamp(2.5rem, 7.5vw, 3.5rem); }
    .daybook-home .login__intro { font-size: 1rem; }
    .product-benefits, .product-plans, .product-faq { padding: 56px 0; }
    .product-section-heading { gap: 18px; margin-bottom: 32px; }
    .product-benefit-grid { gap: 34px; }
    .product-plan-layout { grid-template-columns: 1fr; }
    .product-free, .product-pro { padding: 28px; }
    .product-free > a { margin-top: 12px; }
    .product-faq { gap: 20px; }
    .product-closing { padding: 30px; gap: 24px; }
    .daybook-public .newsstand__colophon { gap: 0 20px; }
    .daybook-public .newsstand__colophon > a:first-child { flex-basis: 100%; }
}
@media (max-width: 399.98px) {
    .public-nav { gap: 4px 9px; font-size: .73rem; }
    .product-free, .product-pro { padding: 24px 20px; }
    .product-offer { padding: 14px 9px; }
    .product-offers strong { font-size: 1.8rem; }
}

.daybook-public .pricing__choose { margin-top: auto; padding-top: 10px; padding-bottom: 10px; }

.q-dialog-focus, .q-dialog-keyboard { display: contents; }
.q-dialog-fields { display: contents; border: 0; padding: 0; margin: 0; min-width: 0; }

/* A themed popover keeps the open options legible on every browser. */
.public-theme { position: relative; display: inline-flex; align-items: center; gap: 6px; min-height: 44px; padding: 6px 32px 6px 12px; border: 1px solid var(--q-line); border-radius: 999px; background: var(--q-surface); color: var(--q-ink-muted); font: 400 .78rem var(--q-font-body); cursor: pointer; }
.public-theme strong { color: var(--q-ink); font-weight: 500; }
.public-theme::after { content: ""; position: absolute; right: 13px; width: 6px; height: 6px; margin-top: -3px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); pointer-events: none; }
.public-theme:hover { border-color: var(--q-ink-muted); }
.public-theme-menu { min-width: 170px; padding: 6px; border: 1px solid var(--q-line); border-radius: 14px; background: var(--q-surface-raised); color: var(--q-ink); box-shadow: var(--q-shadow-2); }
.public-theme-menu .q-menu__item { min-height: 44px; padding: 10px 12px; gap: 10px; border-radius: 8px; background: transparent; color: var(--q-ink); font: 500 .85rem var(--q-font-body); }
.public-theme-menu .q-menu__item:is(:hover, :focus-visible) { background: var(--q-well); color: var(--q-well-ink); outline: 2px solid var(--q-accent-text); outline-offset: -2px; }
.public-theme-menu .q-menu__item[aria-checked="true"] { background: var(--q-well); color: var(--q-well-ink); }
.public-theme-check { width: 16px; visibility: hidden; }
.public-theme-menu [aria-checked="true"] .public-theme-check { visibility: visible; }

/* Public controls retain readable boundaries and feedback in either palette. */
.daybook-public .newsstand__input::placeholder { color: var(--q-ink-muted); opacity: 1; }
.daybook-public :is(.newsstand__input, .newsstand__alt, .product-free > a) {
    border-color: color-mix(in srgb, var(--q-ink-muted) 70%, var(--q-line));
}
.daybook-public :is(.newsstand__alt, .product-free > a):hover {
    color: var(--q-ink); background: var(--q-well); border-color: var(--q-ink-muted);
}
.daybook-public .public-nav__start:hover { background: var(--q-ink-muted); text-decoration: none; }
.daybook-public :is(button, select, summary, input):focus-visible {
    outline: 2px solid var(--q-accent-text); outline-offset: 3px;
}
.daybook-public .newsstand__input:focus { border-color: var(--q-accent-text); }
.daybook-public button:disabled { opacity: .6; cursor: not-allowed; transform: none; box-shadow: none; }
@media (max-width: 600px) {
    .daybook-public .public-nav { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px 12px; }
    .daybook-public .public-nav > public-theme-picker { grid-column: 1 / 3; }
    .daybook-public .public-nav > .public-nav__start { grid-column: 3 / 5; justify-self: end; }
}

/* Prose-link colors must not override the text on filled pricing buttons. */
.daybook-public .notice .q-btn--primary {
    min-height: 46px; padding: 10px 18px; border: 1px solid var(--q-ink); border-radius: 999px;
    background: var(--q-ink); color: var(--q-surface-raised); text-decoration: none;
    font-family: var(--q-font-body); font-size: .85rem; font-weight: 600;
}
.daybook-public .notice .q-btn--primary:hover {
    background: var(--q-ink-muted); border-color: var(--q-ink-muted); color: var(--q-surface-raised);
}
.daybook-public .notice .q-btn--primary:focus-visible { outline: 2px solid var(--q-accent-text); outline-offset: 3px; }
