/*
 * Relay layout — the app chrome and page scaffolding.
 *
 * The mockups are a fixed 1440px canvas and define no breakpoints. This file
 * reproduces those measurements but makes them intrinsically fluid, the way the
 * prototype does: clamp() padding, auto-fit grids, and flex-basis splits so a
 * rail drops beneath the main column instead of crushing it. Desktop is the
 * target; narrow widths stay usable without a dedicated mobile pass.
 */

/* =========================================================================
   Topbar — 56px: logo, the four nav sections, search, approvals, avatar
   ========================================================================= */

.topbar {
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
    display: flex;
    align-items: center;
    gap: clamp(12px, 2vw, 28px);
    height: 56px;
    padding: 0 20px;
    border-bottom: 1px solid var(--line);
    background: var(--surface);
}

.topbar__mark {
    display: flex;
    flex: none;
    align-items: center;
    gap: var(--s2);
    font-family: var(--font-display);
    font-size: 17px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.02em;
    color: var(--ink);
    text-decoration: none;
}

.topbar__mark svg {
    display: block;
}

.topbar__nav {
    display: flex;
    flex: none;
    align-items: center;
    gap: 2px;
}

/* Nav is text pills — no icons. Active is cobalt on its own tint. */
.navpill {
    padding: 6px 12px;
    border-radius: var(--r-pill);
    font-family: var(--font-ui);
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    color: var(--ink-2);
    text-decoration: none;
}

.navpill:hover {
    background: var(--surface-2);
    color: var(--ink);
}

.navpill[aria-current="page"] {
    background: var(--signal-tint);
    color: var(--signal);
}

.topbar__search {
    /* The anchor for the ⌘K results panel, which hangs off the field. */
    position: relative;
    display: flex;
    flex: 1 1 200px;
    justify-content: center;
    min-width: 0;
}

.searchbox {
    display: flex;
    align-items: center;
    gap: var(--s2);
    width: 340px;
    max-width: 100%;
    height: 32px;
    padding: 0 11px;
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--surface-2);
    font-family: var(--font-ui);
    font-size: 13px;
    line-height: 1;
    color: var(--ink-3);
    cursor: text;
}

.searchbox svg {
    flex: none;
}

.searchbox__input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: none;
    font-family: inherit;
    font-size: inherit;
    color: var(--ink);
}

.searchbox__input:focus {
    outline: none;
}

.searchbox__input::placeholder {
    color: var(--ink-3);
}

.kbd {
    flex: none;
    margin-left: auto;
    padding: 3px 4px;
    border: 1px solid var(--line-strong);
    border-radius: 4px;
    font-family: var(--font-data);
    font-size: 10px;
    font-weight: 500;
    line-height: 1;
    color: var(--ink-3);
}

.topbar__end {
    display: flex;
    flex: none;
    align-items: center;
    gap: 10px;
}

.badge-count {
    padding: 4px 9px;
    border: 1px solid color-mix(in srgb, var(--marigold) 30%, transparent);
    border-radius: var(--r-pill);
    background: var(--marigold-tint);
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--marigold);
    text-decoration: none;
}

.avatar {
    display: flex;
    flex: none;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--signal-tint);
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 700;
    line-height: 1;
    color: var(--signal);
    text-decoration: none;
}

/* Role tints, so you can tell whose queue you're in at a glance. */
.avatar--approver {
    background: var(--posted-tint);
    color: var(--posted);
}

.avatar--scheduler {
    background: var(--marigold-tint);
    color: var(--marigold);
}

.avatar--invited {
    border: 1px dashed var(--line-strong);
    background: none;
    color: var(--ink-3);
}

/* The light/dark switch. */
.theme-toggle {
    display: inline-flex;
    flex: none;
    gap: 2px;
    padding: 3px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--surface);
}

.theme-toggle button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 26px;
    border: 0;
    border-radius: var(--r-pill);
    background: transparent;
    color: var(--ink-3);
    cursor: pointer;
}

.theme-toggle button[aria-pressed="true"] {
    background: var(--signal-tint);
    color: var(--signal);
}

/* Quiet by design: it sits beside the avatar and should be findable without
   competing with the nav. Text rather than a glyph, because a door-shaped icon is a
   guess and this is the one control you must not press by accident. */
.signout {
    padding: 4px 8px;
    border: 0;
    border-radius: var(--r-sm);
    background: none;
    font-family: var(--font-ui);
    font-size: 11px;
    font-weight: 500;
    line-height: 1;
    color: var(--ink-3);
    cursor: pointer;
    white-space: nowrap;
}

.signout:hover {
    background: var(--surface-2);
    color: var(--ink);
}

/* =========================================================================
   Context bar — the second row: sub-nav chips or a segmented control,
   the scope title, and up to two actions
   ========================================================================= */

.contextbar {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 46px;
    padding: var(--s2) 20px;
    border-bottom: 1px solid var(--line);
    background: var(--surface);
    flex-wrap: wrap;
}

.contextbar__crumb {
    font-family: var(--font-ui);
    font-size: 12px;
    line-height: 1;
    color: var(--ink-3);
}

/* Sub-nav chips (Library ›, Settings ›). */
.subchip {
    padding: 5px 10px;
    border-radius: 6px;
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
    color: var(--ink-3);
    text-decoration: none;
}

.subchip:hover {
    background: var(--surface-2);
    color: var(--ink);
}

.subchip[aria-current="page"] {
    background: var(--signal-tint);
    color: var(--signal);
}

/* A chip that leaves Relay — the Wagtail admin under Settings. Outlined rather
   than filled: it is a way out, not one of the tabs, and the border is what says
   so before the ↗ does. */
.subchip--out {
    border: 1px solid var(--line-strong);
    color: var(--ink-2);
}

.subchip--out:hover {
    border-color: var(--signal);
    background: transparent;
    color: var(--signal);
}

.contextbar__divider {
    width: 1px;
    height: 22px;
    background: var(--line);
}

.contextbar__title {
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.01em;
    color: var(--ink);
}

/* When the title is a link — the output editor's title goes through to the Base
   Piece — it gets the taller line box the mockups give it there, so the hit area
   isn't a hairline. */
.contextbar__title--link {
    line-height: 1.2;
}

.contextbar__count {
    font-family: var(--font-data);
    font-size: 12px;
    line-height: 1;
    color: var(--ink-3);
}

.contextbar__actions {
    display: flex;
    align-items: center;
    gap: var(--s2);
}

/* =========================================================================
   Page body
   ========================================================================= */

.page {
    padding: 26px clamp(16px, 2vw, 28px) 34px;
}

/* The output editors run edge to edge: the preview rail is a wall against the
   right side of the window, not a card floating inside a padded page. Only the
   banners keep an inset, because a full-bleed banner would read as chrome. */
.page--flush {
    padding: 0;
}

.page--flush > .banner {
    margin: var(--s4) 20px 0;
}

.page__head {
    margin-bottom: 22px;
}

.page__eyebrow {
    margin-bottom: 6px;
    font-family: var(--font-data);
    font-size: 12px;
    line-height: 1;
    color: var(--ink-3);
}

.page__title {
    margin: 0 0 4px;
    font-family: var(--font-display);
    font-size: var(--t-h1);
    font-weight: 600;
    line-height: 1.15;
    letter-spacing: -0.025em;
    /* Not `balance`. Today's heading is `{{ headline }}` — written by the read
       model, not by a person — and balance equalises a two-line heading by
       pulling the first line in, so a sentence that would have filled the column
       breaks halfway across it instead and looks truncated. `pretty` leaves the
       measure alone and only avoids a one-word last line. */
    text-wrap: pretty;
    color: var(--ink);
}

/* One measure, from the token, because there was not one before: the base was
   64ch and five screens each inlined their own 70ch / 72ch / 74ch over it, which
   is what a value being wrong looks like when it is overridden rather than
   fixed.

   `--measure-body` rather than `--measure-lede`, even though this is the lede.
   The narrow measure is the right call for a column of paragraphs; a page's
   introduction is one or two sentences sitting above a full-width head, and at
   64ch it broke a third of the way across the page and read as truncated. 86ch
   is still inside the comfortable range the token file's own note cites.

   `pretty` for the same reason `.page__title` has it: whatever the measure, the
   last line should not be left a stub. */
.page__lede {
    max-width: var(--measure-body);
    margin: 0;
    font-size: var(--t-body);
    line-height: 1.5;
    text-wrap: pretty;
    color: var(--ink-2);
}

/* Main column + rail. The flex-basis pair means the rail drops below the main
   column once the row can't hold both, instead of squeezing to nothing. */
.split {
    display: flex;
    flex-wrap: wrap;
    gap: 26px;
    align-items: flex-start;
}

.split__main {
    display: flex;
    flex: 155 1 520px;
    flex-direction: column;
    gap: 22px;
    min-width: 0;
}

/* The rail's width is the screen's to set, via `--rail`.
   Every mockup pins its rail — 288px on the calendar, 452px beside an output
   preview — and lets the main column absorb what's left, which is what
   `grid-template-columns: minmax(0,1fr) <n>px` means. So `flex-grow` is 0 here:
   a growing rail splits the surplus with the main column instead, which on a
   1440px canvas cost the main column around 200px and squeezed wide tables for
   no reason. `flex-shrink` stays 1 so the rail still gives way, and `.split`'s
   wrap still drops it under the main column at narrow widths. */
.split__rail {
    display: flex;
    flex: 0 1 var(--rail, 330px);
    flex-direction: column;
    gap: 14px;
    min-width: 0;
}

/* A left list + detail pane, used by Settings → Pillars. */
.master-detail {
    display: flex;
    flex-wrap: wrap;
    gap: 0;
    align-items: stretch;
    border: 1px solid var(--line);
    border-radius: var(--r-lg);
    background: var(--surface);
    overflow: hidden;
}

.master-detail__list {
    display: flex;
    flex: 1 1 236px;
    flex-direction: column;
    gap: 4px;
    max-width: 236px;
    padding: var(--s4) var(--s3);
    border-right: 1px solid var(--line);
}

.master-detail__pane {
    display: flex;
    flex: 999 1 420px;
    flex-direction: column;
    gap: 18px;
    min-width: 0;
    padding: var(--s5) 26px;
}

/* Rows in the master list. */
.listrow {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 9px 10px;
    border-radius: var(--r-md);
    font-family: var(--font-ui);
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1;
    color: var(--ink-2);
    text-decoration: none;
}

.listrow:hover {
    background: var(--surface-2);
    color: var(--ink);
}

.listrow[aria-current="page"] {
    background: var(--signal-tint);
    color: var(--signal);
}

.listrow__dot {
    flex: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--line-strong);
}

.listrow[aria-current="page"] .listrow__dot {
    background: var(--signal);
}

.listrow__count {
    margin-left: auto;
    font-family: var(--font-data);
    font-size: 11px;
    line-height: 1;
    color: var(--ink-3);
}

.listrow--add {
    border: 1px dashed var(--line-strong);
    color: var(--ink-3);
}

/* A filter bar sitting above a table. */
.filterbar {
    display: flex;
    align-items: flex-end;
    gap: 12px;
    flex-wrap: wrap;
    padding: var(--s4) 22px;
    border-bottom: 1px solid var(--line);
    background: var(--surface-2);
}

/* A bare row of controls above a list — search, a few filter chips, then the
   action. Distinct from `.filterbar`, which is a boxed bar inside a panel head. */
.toolbar {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex-wrap: wrap;
}

.filterbar .field {
    margin-bottom: 0;
    max-width: 148px;
}

/* Generic grids the screens reuse. */
.grid-4 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
    gap: 12px;
}

.grid-3 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--s3);
}

/* Three across, and three across only: the generation cards are a set — text,
   images, meaning search — and 2+1 reads as one of them being different. Below
   the breakpoint they stack rather than reflowing into an uneven row. */
.grid-3--set {
    grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 900px) {
    .grid-3--set {
        grid-template-columns: minmax(0, 1fr);
    }
}

.grid-2 {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: var(--s3);
}

/* Anything that must not squash — SVG diagrams, very wide tables. */
.scroll-x {
    overflow-x: auto;
}

/* =========================================================================
   The one breakpoint the design system defines
   ========================================================================= */

@media (max-width: 820px) {
    .topbar {
        flex-wrap: wrap;
        height: auto;
        padding: var(--s2) var(--s3);
    }

    .topbar__search {
        order: 5;
        flex-basis: 100%;
        justify-content: flex-start;
    }

    .searchbox {
        width: 100%;
    }

    .master-detail__list {
        max-width: none;
        border-right: 0;
        border-bottom: 1px solid var(--line);
    }
}

/* =========================================================================
   Shared small pieces used across the screens
   ========================================================================= */

/* A heading row: label on the left, a figure or link on the right. */
.section-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3);
    margin-bottom: 10px;
    font-size: 12px;
    line-height: 1;
}

.stack {
    display: flex;
    flex-direction: column;
    gap: var(--s2);
}

.stack--loose {
    gap: 11px;
}

.btn--block {
    width: 100%;
    justify-content: flex-start;
    font-size: 13px;
    line-height: 1;
    padding: 9px 13px;
}

/* A panel outlined in the action colour — at most one per screen. */
.panel--accent {
    border-color: var(--signal);
}

.rail-more {
    display: block;
    margin-top: 9px;
    padding-top: 9px;
    border-top: 1px solid var(--line);
    font-size: 12px;
    font-weight: 600;
    line-height: 1;
}

/* --- Attention rows (Today's "Needs you now") ---------------------------
   The left stripe carries severity, so the ordering is legible without
   reading: critical, then waiting-on-a-person, then idle work. */
.attention {
    display: grid;
    grid-template-columns: 26px minmax(0, 1fr) auto auto;
    align-items: center;
    gap: 14px;
    padding: 13px 18px;
    border-bottom: 1px solid var(--line);
    border-left: 3px solid var(--line-strong);
}

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

.attention--critical {
    border-left-color: var(--critical);
}

.attention--warn {
    border-left-color: var(--marigold);
}

.attention--idle {
    border-left-color: var(--ink-3);
}

.attention__ic {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    font-size: 12px;
    font-weight: 700;
}

.attention--critical .attention__ic {
    background: var(--critical-tint);
    color: var(--critical);
}

.attention--warn .attention__ic {
    background: var(--marigold-tint);
    color: var(--marigold);
}

.attention--idle .attention__ic {
    border: 1px solid var(--line);
    background: var(--surface-2);
    color: var(--ink-3);
}

.attention__text {
    min-width: 0;
}

.attention__title {
    display: block;
    font-size: 14px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--ink);
}

.attention__detail {
    display: block;
    font-family: var(--font-data);
    font-size: 12px;
    line-height: 1.4;
    color: var(--ink-3);
}

/* Today's week strip is the calendar grid at a smaller scale. */
.cal--mini {
    gap: 8px;
}

.cal--mini .cal__day {
    min-height: 112px;
}

/* --- Pulse rows --------------------------------------------------------- */
.pulse-row {
    display: flex;
    flex-direction: column;
    gap: 3px;
    text-decoration: none;
}

.pulse-row__title {
    font-size: 13px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--ink);
}

.pulse-row:hover .pulse-row__title {
    color: var(--signal);
}

.pulse-row__meta {
    font-family: var(--font-data);
    font-size: 11px;
    line-height: 1.3;
    color: var(--ink-3);
}

@media (max-width: 820px) {
    .attention {
        grid-template-columns: 26px minmax(0, 1fr);
    }
}

/* =========================================================================
   Calendar chrome
   ========================================================================= */

/* ‹ July 2026 › Today */
.calnav {
    display: flex;
    align-items: center;
    gap: var(--s2);
}

.calnav__step {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 26px;
    height: 26px;
    border: 1px solid var(--line-strong);
    border-radius: 7px;
    font-size: 13px;
    line-height: 1;
    color: var(--ink-2);
    text-decoration: none;
}

.calnav__step:hover {
    border-color: var(--signal);
    color: var(--signal);
}

.calnav__label {
    min-width: 120px;
    font-family: var(--font-display);
    font-size: 15px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: -0.01em;
    text-align: center;
    color: var(--ink);
}

.calfilters {
    display: flex;
    align-items: center;
    gap: 7px;
    flex-wrap: wrap;
}

/* A select that reads as a pill. On the grid views platform and status are a
   lens over what's already shown, not a query to submit, so they look lighter
   than the list view's filter bar. */
.pillselect {
    appearance: none;
    padding: 6px 26px 6px 11px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background-color: var(--surface-2);
    background-image:
        linear-gradient(45deg, transparent 50%, var(--ink-3) 50%),
        linear-gradient(135deg, var(--ink-3) 50%, transparent 50%);
    background-position: calc(100% - 14px) 55%, calc(100% - 9px) 55%;
    background-size: 5px 5px, 5px 5px;
    background-repeat: no-repeat;
    font-family: var(--font-ui);
    font-size: 12px;
    font-weight: 500;
    line-height: 1;
    color: var(--ink-2);
    cursor: pointer;
}

.pillselect--on {
    border-color: color-mix(in srgb, var(--signal) 30%, transparent);
    background-color: var(--signal-tint);
    color: var(--signal);
    font-weight: 600;
}

/* The month grid keeps a fixed row height so the shape of a month is
   comparable at a glance; the week grid can afford taller cells. */
.cal {
    grid-auto-rows: 104px;
}

.cal--week {
    grid-auto-rows: minmax(200px, auto);
}

.cal__legend {
    display: flex;
    align-items: center;
    gap: 18px;
    padding: 10px 2px 0;
    font-size: 11px;
    line-height: 1;
    color: var(--ink-3);
}

.cal__legend-item {
    display: flex;
    align-items: center;
    gap: 6px;
}

.cal__legend-swatch {
    width: 10px;
    height: 10px;
    border-radius: 2px;
}

/* --- Drafts dock -------------------------------------------------------- */

.dock {
    display: flex;
    flex-direction: column;
    gap: var(--s2);
    padding: 10px;
}

.dock__card {
    display: flex;
    flex-direction: column;
    gap: 4px;
    padding: 9px 10px;
    border: 1px solid var(--line);
    border-left: 3px solid var(--ink-3);
    border-radius: var(--r-md);
    background: var(--surface-2);
}

.dock__card[draggable="true"] {
    cursor: grab;
}

.dock__card[draggable="true"]:active {
    cursor: grabbing;
}

.dock__kicker {
    display: flex;
    align-items: center;
    gap: 6px;
    font-family: var(--font-data);
    font-size: 10px;
    line-height: 1;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--ink-3);
}

.dock__title {
    font-size: 12.5px;
    font-weight: 600;
    line-height: 1.35;
    color: var(--ink);
    text-decoration: none;
}

.dock__title:hover {
    color: var(--signal);
}

.dock__hint {
    font-family: var(--font-data);
    font-size: 10.5px;
    line-height: 1;
    color: var(--ink-3);
}

/* The dock card's "Place…" — opens the schedule sheet. A quiet outline rather
   than a filled button: the card is a small object, and this is one of two ways
   to do the same thing rather than its headline action. */
.dock__place {
    align-self: flex-start;
    margin-top: 5px;
    padding: 5px 9px;
    border: 1px solid var(--line-strong);
    border-radius: var(--r-sm);
    background: var(--surface);
    font-family: var(--font-ui);
    font-size: 11.5px;
    font-weight: 600;
    line-height: 1;
    color: var(--signal);
    cursor: pointer;
}

.dock__place:hover {
    border-color: var(--signal);
    background: var(--signal-tint);
}

.gaps__unset {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 7px;
    margin-top: 11px;
    padding-top: 11px;
    border-top: 1px solid var(--line);
}

@media (max-width: 820px) {
    .cal {
        grid-auto-rows: minmax(88px, auto);
    }
}

/* =========================================================================
   Grouped listings (Core Articles by pillar)
   ========================================================================= */

.pillar-group {
    margin-bottom: var(--s6);
}

.pillar-group__head {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-bottom: var(--s3);
    padding-bottom: var(--s2);
    border-bottom: 1px solid var(--line);
}

.pillar-group__name {
    font-family: var(--font-ui);
    font-size: 13px;
    font-weight: 600;
    line-height: 1;
    color: var(--ink);
}

/* The "add another" tile that closes each group. Dashed so it reads as an
   affordance rather than a record. */
.card--add {
    border-style: dashed;
    box-shadow: none;
    background: none;
}

/* It stands to the same height as the records beside it, so its content is centred
   rather than clinging to the top of an otherwise empty box. Its note is not a
   footer — it explains the button — so it stays with it instead of being pushed to
   the floor the way a record's meta line is. */
.cards .card--add .card__body {
    justify-content: center;
}

/* --- Feed health rows (Pulse rail) -------------------------------------- */

.feedrow {
    display: grid;
    grid-template-columns: 8px minmax(0, 1fr) auto;
    align-items: center;
    gap: 9px;
}

.feedrow__dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
}

/* A row whose subject is spent — an expired pulse item — is dimmed rather than
   hidden: knowing the pulse has gone quiet is itself the useful signal. */
.row--spent {
    opacity: .55;
}

/* --- Approvals ---------------------------------------------------------- */

/* Each card carries a diff, so it needs width — but capped, or a single pending
   change stretches a paragraph across 1400px and becomes unreadable. */
.grid-approvals {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(420px, 620px));
    gap: var(--s3);
    align-items: start;
}

.subchip__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 16px;
    height: 16px;
    margin-left: 5px;
    padding: 0 4px;
    border-radius: var(--r-pill);
    background: var(--marigold-tint);
    font-family: var(--font-data);
    font-size: 9.5px;
    font-weight: 700;
    color: var(--marigold);
}

/* The consequence of a decision. Amber when there is something downstream to
   break; quiet when there genuinely isn't. */
.blast {
    display: flex;
    flex-direction: column;
    gap: 5px;
    margin-top: var(--s3);
    padding: var(--s3);
    border: 1px solid var(--line);
    border-radius: var(--r-md);
    background: var(--surface-2);
}

.blast--wide {
    border-color: color-mix(in srgb, var(--marigold) 40%, transparent);
    background: var(--marigold-tint);
}

/* --- Content graph ------------------------------------------------------- */
/* Every colour here is a token, which is what lets the same SVG carry both
   themes. Fills and strokes are set in CSS rather than as SVG presentation
   attributes so a node only has to declare what state it is in. */

.gphbar {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3);
    font: 400 11.5px/1 var(--font-data);
    color: var(--ink-3);
}

/* The SVG is a fixed aspect ratio, so it scales down with the column rather
   than needing a breakpoint. The scroller is the floor: below ~620px the text
   inside the nodes would stop being legible, so pan instead of shrink. */
.gphwrap {
    overflow-x: auto;
    overscroll-behavior-x: contain;
}

.gph {
    display: block;
    width: 100%;
    min-width: 620px;
    height: auto;
    font-family: var(--font-data);
    /* SVG text is single-line and positioned by baseline, so the body's 1.5
       would only show up as a computed-style difference from the mockup. */
    line-height: normal;
}

.gph__edge {
    fill: none;
    stroke: var(--line-strong);
}

.gph__edge--rippled {
    stroke: var(--marigold);
}

.gph__node {
    cursor: pointer;
}

.gph__node:focus {
    outline: none;
}

.gph__box {
    fill: var(--surface);
    stroke: var(--line-strong);
    stroke-width: 1.4;
    transition: filter var(--ease);
}

.gph__node:hover .gph__box,
.gph__node:focus-visible .gph__box {
    stroke: var(--signal);
}

.gph__node:focus-visible .gph__box {
    stroke-width: 2.2;
}

.gph__eyebrow {
    fill: var(--ink-3);
    font-size: 8.5px;
    letter-spacing: 1px;
}

.gph__label {
    fill: var(--ink);
    font-size: 10px;
    font-weight: 600;
}

/* Pillar: the one node that is a heading rather than a thing you open. */
.gph__node--pillar .gph__box {
    fill: var(--signal-tint);
    stroke: var(--signal);
}

.gph__node--pillar .gph__eyebrow {
    fill: var(--signal);
}

/* Core articles sit on a tinted ground so the two middle columns don't read as
   one long row of identical cards. */
.gph__node--article .gph__box {
    fill: var(--surface-2);
}

/* Rippled: downstream of an unapproved change, at every level. */
.gph__node--rippled .gph__box {
    fill: var(--marigold-tint);
    stroke: var(--marigold);
    stroke-width: 1.8;
}

.gph__node--rippled .gph__eyebrow {
    fill: var(--marigold);
}

/* A flagged base piece keeps a plain ground — the amber outline is enough, and
   tinting it too would compete with the outputs that actually need redoing. */
.gph__node--piece.gph__node--rippled .gph__box {
    fill: var(--surface);
}

.gph__node--dashed .gph__box {
    stroke-dasharray: 4 3;
}

/* --- Output leaves: a status stripe and a smaller, single-line label. */
.gph__node--output .gph__box {
    fill: var(--surface-2);
    stroke-width: 1;
}

.gph__node--output .gph__label {
    fill: var(--ink-2);
    font-size: 9.5px;
    font-weight: 400;
}

.gph__node--output.gph__node--rippled .gph__box {
    fill: var(--marigold-tint);
    stroke-width: 1;
}

.gph__node--output.gph__node--rippled .gph__label {
    fill: var(--ink);
}

.gph__node--posted .gph__box {
    fill: var(--posted-tint);
}

.gph__stripe {
    fill: var(--ink-3);
}

.gph__node--posted .gph__stripe {
    fill: var(--posted);
}

.gph__node--scheduled .gph__stripe {
    fill: var(--signal);
}

.gph__node--rippled .gph__stripe {
    fill: var(--marigold);
}

.gph__flag {
    fill: var(--marigold);
    /* The mono stack has no U+2691 on most systems, and a missing glyph is
       worse than a slightly different one. */
    font-family: var(--font-ui);
    font-size: 9px;
    font-weight: 700;
}

/* The legend carries the three colours the graph uses and nothing else. Rules
   you have to hold in your head are rules you have to be told once. */
.gph__legend {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 18px;
    border-top: 1px solid var(--line);
    padding-top: 11px;
    font: 400 11px/1 var(--font-ui);
    color: var(--ink-3);
}

.gph__legend-item {
    display: flex;
    align-items: center;
    gap: 6px;
}

.gph__legend-line {
    width: 14px;
    height: 2px;
    background: var(--marigold);
}

.gph__legend-chip {
    width: 10px;
    height: 10px;
    border-radius: 2px;
}

.gph__legend-hint {
    margin-left: auto;
    font-family: var(--font-data);
}

/* --- Rail: ripple, coverage, orphans ------------------------------------- */

.ripplerow {
    display: flex;
    justify-content: space-between;
    gap: var(--s3);
    font: 400 12px/1 var(--font-ui);
    color: var(--ink-2);
    padding: 6px 0;
    border-bottom: 1px solid var(--line);
}

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

.ripplerow__verdict {
    font-family: var(--font-data);
    color: var(--ink);
    white-space: nowrap;
}

.ripplerow__verdict--act {
    color: var(--marigold);
}

.ripplerow__verdict--safe {
    color: var(--ink-3);
}

/* Coverage bars. Named `cov` rather than `bar`, which relay-components.css
   already uses for the generation progress track. */
.covs {
    display: grid;
    gap: 9px;
}

.cov {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.cov__head {
    display: flex;
    justify-content: space-between;
    gap: var(--s2);
    font: 600 11.5px/1 var(--font-ui);
    color: var(--ink);
}

.cov__value {
    font-family: var(--font-data);
    font-weight: 400;
    color: var(--ink-3);
}

.cov__track {
    display: block;
    height: 8px;
    border-radius: var(--r-pill);
    background: var(--surface-2);
    border: 1px solid var(--line);
    overflow: hidden;
}

.cov__fill {
    display: block;
    height: 100%;
    background: color-mix(in srgb, var(--signal) 55%, var(--surface));
}

/* Amber where the load rests on too few articles: the bar is the same length,
   but the risk isn't. */
.cov--thin .cov__fill {
    background: color-mix(in srgb, var(--marigold) 60%, var(--surface));
}

.orphanrow {
    display: flex;
    justify-content: space-between;
    gap: var(--s3);
    font: 400 12px/1.5 var(--font-ui);
    color: var(--ink-2);
}

.orphanrow__count {
    font-family: var(--font-data);
    color: var(--ink);
}

/* The graph's own panel: a little roomier than the shared body padding, because
   the SVG needs breathing space on both sides of a 1000-unit canvas. */
.gphpanel {
    display: flex;
    flex-direction: column;
    gap: var(--s3);
    padding: 18px 20px;
    min-width: 0;
}

/* A pill toggle that lives in the context bar next to the two selects, matching
   their height and weight. On when it is in the URL. */
/* A filter that reads as a pill. Used both as a link that sets a query param
   and as a two-state toggle; `aria-current`/`aria-pressed` is what turns it on,
   so the state lives in the markup rather than in a second class. */
.pilltoggle {
    padding: 7px 12px;
    border: 1px solid var(--line);
    border-radius: var(--r-pill);
    background: var(--surface);
    font: 500 12px/1 var(--font-ui);
    color: var(--ink-2);
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}

.pilltoggle:hover {
    border-color: var(--line-strong);
    color: var(--ink);
}

.pilltoggle[aria-pressed="true"],
.pilltoggle[aria-current="page"] {
    border-color: color-mix(in srgb, var(--signal) 30%, transparent);
    background: var(--signal-tint);
    color: var(--signal);
}

/* Where the mockup gives the toggle an action's weight rather than a filter's. */
.pilltoggle--strong {
    font-weight: 600;
}

/* The drawer scale: the same pill a notch smaller, because it shares a 456px
   row with the compare link. */
.pilltoggle--sm {
    padding: 6px 11px;
    font-size: 11.5px;
}

/* Amber-bordered panel: something downstream needs a decision. `panel--accent`
   is the blue equivalent for panels that are merely primary. */
.panel--warn {
    border-color: var(--marigold);
}

/* =========================================================================
   Output editor — the copy on the left, the platform preview on the right
   ========================================================================= */

/* Two columns, edge to edge, with the rail a fixed 452px because the preview
   inside it is a fixed-shape object: a phone frame or a feed card doesn't
   usefully get wider. The main column takes whatever is left. */
.editor {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 452px;
    min-height: 700px;
}

.editor__main {
    display: flex;
    flex-direction: column;
    gap: 18px;
    min-width: 0;
    padding: 22px 24px 28px;
}

.editor__rail {
    display: flex;
    flex-direction: column;
    gap: 13px;
    padding: 22px 24px;
    border-left: 1px solid var(--line);
    background: var(--surface-2);
}

/* Below the breakpoint the rail goes under the copy rather than shrinking: a
   squeezed preview stops being a preview of anything. */
@media (max-width: 1140px) {
    .editor {
        grid-template-columns: minmax(0, 1fr);
    }

    .editor__rail {
        border-top: 1px solid var(--line);
        border-left: 0;
    }
}

/* A group inside either column: its own header row, then the thing itself. */
.editor__group {
    display: flex;
    flex-direction: column;
    gap: 7px;
    min-width: 0;
}

/* The groups below the fold — Scheduling, After you post — are separated by a
   rule rather than a card, so the column still reads as one document. */
.editor__group--ruled {
    gap: 9px;
    padding-top: var(--s4);
    border-top: 1px solid var(--line);
}

/* A row of small labelled controls that wraps: status beside its date, the
   link field beside its button. */
.editor__row {
    display: flex;
    align-items: flex-end;
    gap: var(--s3);
    flex-wrap: wrap;
}

/* `.field` carries a bottom margin for when fields are stacked in a column. In
   a row aligned to `flex-end` that margin is measured *into* the alignment, so
   every field except the last one — which `.field:last-child` zeroes — sat 16px
   above the last field and above the button beside it. Scheduling's three
   controls and After-you-post's link-plus-button were both off by exactly that.
   The row's own `gap` is what spaces them here. */
.editor__row .field {
    margin-bottom: 0;
}

/* An action that cannot be taken yet stays visible and legible-but-quiet — the
   states gallery's rule: never a dead end, always a reason. */
.editor__row--waiting {
    opacity: 0.55;
}
