/* ==========================================================================
   Fey — components
   The primitives the whole app is built from. Written once, here, rather than
   inline in pages: the reason for leaving a component library behind was to
   own these, and owning them only pays off if there is one copy of each.
   ========================================================================== */

/* ── Card ── */

.fey-card {
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius);
    box-shadow: var(--fey-lift);
}

.fey-card-pad { padding: var(--s5); }

.fey-card-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--s4);
    padding: var(--s4) var(--s5);
    border-bottom: 1px solid var(--fey-line);
}

.fey-card-title { font-size: 14px; font-weight: 550; letter-spacing: -0.01em; }
.fey-card-body { padding: var(--s5); }
.fey-card-body-tight { padding: var(--s4) var(--s5); }

.fey-card-foot {
    padding: var(--s3) var(--s5);
    border-top: 1px solid var(--fey-line);
    background: var(--fey-surface-sunken);
    border-radius: 0 0 var(--fey-radius) var(--fey-radius);
}

/* A card that is also a link to somewhere. The lift on hover is small on
   purpose — a whole panel jumping is noise, not feedback. */
.fey-card-link {
    display: block;
    color: inherit;
    text-decoration: none;
    transition: border-color 0.18s var(--fey-ease-soft),
                box-shadow 0.18s var(--fey-ease-soft),
                transform 0.18s var(--fey-ease);
}

.fey-card-link:hover {
    text-decoration: none;
    border-color: var(--fey-line-strong);
    box-shadow: var(--fey-lift-lg);
    transform: translateY(-2px);
}

/* ── Button ── */

.fey-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--s2);
    padding: 8px 15px;
    border: 1px solid var(--fey-line-strong);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-surface);
    color: var(--fey-ink);
    font-size: 13px;
    font-weight: 500;
    line-height: 1.4;
    cursor: pointer;
    white-space: nowrap;
    text-decoration: none;
    transition: background 0.16s var(--fey-ease-soft),
                border-color 0.16s var(--fey-ease-soft),
                box-shadow 0.16s var(--fey-ease-soft),
                transform 0.12s var(--fey-ease);
}

.fey-btn:hover:not(:disabled) {
    background: var(--fey-primary-soft);
    border-color: var(--fey-primary);
    text-decoration: none;
}

/* Pressing moves the button a single pixel. Enough to feel, not enough to see. */
.fey-btn:active:not(:disabled) { transform: translateY(1px); }

.fey-btn:disabled { opacity: 0.45; cursor: not-allowed; }

.fey-btn-primary {
    background: var(--fey-primary);
    border-color: var(--fey-primary);
    color: #fff;
    box-shadow: 0 1px 2px rgba(93, 82, 138, 0.18);
}

.fey-btn-primary:hover:not(:disabled) {
    background: var(--fey-primary-deep);
    border-color: var(--fey-primary-deep);
    box-shadow: 0 2px 10px rgba(93, 82, 138, 0.26);
}

.fey-btn-ghost { background: transparent; border-color: transparent; color: var(--fey-ink-soft); }
.fey-btn-ghost:hover:not(:disabled) { background: var(--fey-primary-soft); color: var(--fey-ink); border-color: transparent; }

.fey-btn-danger { color: var(--fey-red); border-color: rgba(212, 95, 95, 0.30); }
.fey-btn-danger:hover:not(:disabled) { background: var(--fey-red-soft); border-color: var(--fey-red); }

.fey-btn-sm { padding: 5px 11px; font-size: 12px; border-radius: 7px; }
.fey-btn-lg { padding: 11px 20px; font-size: 14px; }
.fey-btn-block { width: 100%; }

/* ── Fields ── */

.fey-field { display: flex; flex-direction: column; gap: 6px; }
.fey-field > label { font-size: 12.5px; font-weight: 500; color: var(--fey-ink-soft); }

.fey-input,
.fey-select,
.fey-textarea {
    width: 100%;
    padding: 9px 12px;
    border: 1px solid var(--fey-line-strong);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-surface);
    font-size: 13.5px;
    color: var(--fey-ink);
    transition: border-color 0.16s var(--fey-ease-soft), box-shadow 0.16s var(--fey-ease-soft);
}

.fey-input::placeholder, .fey-textarea::placeholder { color: var(--fey-ink-faint); }

.fey-input:focus,
.fey-select:focus,
.fey-textarea:focus {
    outline: none;
    border-color: var(--fey-primary);
    box-shadow: var(--fey-ring);
}

.fey-input:disabled, .fey-select:disabled { background: var(--fey-surface-sunken); color: var(--fey-ink-faint); }

.fey-input-mono { font-family: var(--fey-mono); font-size: 12.5px; }

.fey-textarea { resize: vertical; min-height: 90px; line-height: 1.6; }

.fey-select {
    appearance: none;
    padding-right: 32px;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%23A5A0B5' stroke-width='1.4' fill='none' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 11px center;
}

.fey-field-hint { font-size: 11.5px; color: var(--fey-ink-faint); line-height: 1.5; }
.fey-field-error { font-size: 11.5px; color: var(--fey-red); }

.fey-input-invalid { border-color: var(--fey-red); }
.fey-input-invalid:focus { box-shadow: 0 0 0 3px var(--fey-red-soft); }

/* An input with a fixed suffix, for the subdomain field: you type the label and
   the domain is shown attached rather than explained in a hint below. */
.fey-input-affix {
    display: flex;
    align-items: stretch;
    border: 1px solid var(--fey-line-strong);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-surface);
    overflow: hidden;
    transition: border-color 0.16s var(--fey-ease-soft), box-shadow 0.16s var(--fey-ease-soft);
}

.fey-input-affix:focus-within { border-color: var(--fey-primary); box-shadow: var(--fey-ring); }
.fey-input-affix .fey-input { border: none; box-shadow: none; border-radius: 0; }
.fey-input-affix .fey-input:focus { box-shadow: none; }

.fey-affix {
    display: flex;
    align-items: center;
    padding: 0 12px;
    background: var(--fey-surface-sunken);
    border-left: 1px solid var(--fey-line);
    font-family: var(--fey-mono);
    font-size: 12px;
    color: var(--fey-ink-faint);
    white-space: nowrap;
}

.fey-check { display: inline-flex; align-items: center; gap: var(--s2); cursor: pointer; font-size: 13px; }
.fey-check input { width: 15px; height: 15px; accent-color: var(--fey-primary); cursor: pointer; }

/* ── Badge ── */

.fey-badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    white-space: nowrap;
}

.fey-badge-neutral { background: rgba(139, 126, 200, 0.09); color: var(--fey-ink-soft); }
.fey-badge-green   { background: var(--fey-green-soft); color: #2F7A5A; }
.fey-badge-amber   { background: var(--fey-amber-soft); color: #9A6224; }
.fey-badge-red     { background: var(--fey-red-soft);   color: #A63F3F; }
.fey-badge-blue    { background: var(--fey-blue-soft);  color: #3D6BA8; }
.fey-badge-violet  { background: var(--fey-primary-soft); color: var(--fey-primary-deep); }

.fey-dot { width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0; }
.fey-dot-green   { background: var(--fey-green); }
.fey-dot-amber   { background: var(--fey-amber); }
.fey-dot-red     { background: var(--fey-red); }
.fey-dot-neutral { background: var(--fey-ink-faint); }
.fey-dot-violet  { background: var(--fey-primary); }

/* A slot that is deploying pulses. It is the only thing in the app that moves
   on its own, which is what makes it readable across a page of still panels. */
.fey-dot-pulse { animation: fey-pulse 1.7s var(--fey-ease-soft) infinite; }

@keyframes fey-pulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 currentColor; }
    50%      { opacity: 0.65; box-shadow: 0 0 0 4px transparent; }
}

/* ── Disk bar ──
   The signature object of the Ship module: a server drawn as the disk you are
   paying for, cut into the slots that share it. Assigned space is a segment,
   the used part of it is a darker inset, and what nobody has claimed is left
   visibly, deliberately empty. It is the one screen that answers "where is my
   money going" without a legend. */

.fey-diskbar {
    display: flex;
    height: 34px;
    border-radius: var(--fey-radius-sm);
    overflow: hidden;
    background:
        repeating-linear-gradient(
            -45deg,
            rgba(139, 126, 200, 0.055) 0 6px,
            transparent 6px 12px
        ),
        var(--fey-surface-sunken);
    border: 1px solid var(--fey-line);
}

.fey-diskbar-seg {
    position: relative;
    min-width: 3px;
    background: var(--fey-primary-tint);
    border-right: 1px solid var(--fey-surface);
    transition: filter 0.16s var(--fey-ease-soft);
    cursor: default;
    overflow: hidden;
}

.fey-diskbar-seg:last-child { border-right: none; }
.fey-diskbar-seg:hover { filter: brightness(0.94); }

/* The filled part of a slot's own allotment. Two shades of the same hue, so a
   full slot and an empty one differ in weight rather than in colour. */
.fey-diskbar-fill {
    position: absolute;
    inset: 0 auto 0 0;
    background: var(--fey-primary);
    opacity: 0.55;
}

.fey-diskbar-seg.over .fey-diskbar-fill { background: var(--fey-red); opacity: 0.6; }
.fey-diskbar-seg.warn .fey-diskbar-fill { background: var(--fey-amber); opacity: 0.6; }

.fey-diskbar-label {
    position: relative;
    z-index: 1;
    padding: 0 8px;
    font-size: 10.5px;
    font-weight: 600;
    line-height: 34px;
    color: var(--fey-primary-deep);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fey-diskbar-legend {
    display: flex;
    flex-wrap: wrap;
    gap: var(--s4);
    margin-top: var(--s3);
    font-size: 11.5px;
    color: var(--fey-ink-soft);
}

.fey-diskbar-key { display: inline-flex; align-items: center; gap: 6px; }
.fey-diskbar-swatch { width: 10px; height: 10px; border-radius: 3px; }

/* ── Meter ──
   The single-slot version of the disk bar: one thin line under a figure. */

.fey-meter { height: 4px; border-radius: 999px; background: rgba(139, 126, 200, 0.12); overflow: hidden; }
.fey-meter-fill { height: 100%; border-radius: 999px; background: var(--fey-primary); transition: width 0.5s var(--fey-ease); }
.fey-meter-fill.warn { background: var(--fey-amber); }
.fey-meter-fill.over { background: var(--fey-red); }

/* ── Table ── */

.fey-table { width: 100%; border-collapse: collapse; font-size: 13px; }

.fey-table th {
    text-align: left;
    padding: 0 var(--s3) var(--s2);
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--fey-ink-faint);
    border-bottom: 1px solid var(--fey-line);
    white-space: nowrap;
}

.fey-table td { padding: 11px var(--s3); border-bottom: 1px solid var(--fey-line); vertical-align: middle; }
.fey-table tbody tr:last-child td { border-bottom: none; }
.fey-table tbody tr { transition: background 0.14s var(--fey-ease-soft); }
.fey-table tbody tr:hover { background: var(--fey-primary-soft); }
.fey-table .num { text-align: right; font-variant-numeric: tabular-nums; }

.fey-scroll-x { overflow-x: auto; }

/* ── Empty state ── */

.fey-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: var(--s2);
    padding: var(--s8) var(--s5);
    text-align: center;
}

.fey-empty-title { font-family: var(--fey-display); font-size: 19px; color: var(--fey-ink); }
.fey-empty-text { font-size: 13px; color: var(--fey-ink-soft); max-width: 40ch; line-height: 1.6; }
.fey-empty > .fey-btn { margin-top: var(--s3); }

/* ── Notice ── */

.fey-notice {
    display: flex;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    border-radius: var(--fey-radius-sm);
    font-size: 13px;
    line-height: 1.55;
    border: 1px solid transparent;
}

.fey-notice-info  { background: var(--fey-primary-soft); border-color: var(--fey-line); color: var(--fey-ink); }
.fey-notice-warn  { background: var(--fey-amber-soft); border-color: rgba(217,146,72,0.24); color: #7C4E1B; }
.fey-notice-error { background: var(--fey-red-soft);   border-color: rgba(212,95,95,0.24); color: #8E3535; }
.fey-notice-good  { background: var(--fey-green-soft); border-color: rgba(79,185,138,0.24); color: #256A4C; }

.fey-notice-mark { flex-shrink: 0; font-weight: 700; line-height: 1.5; }

/* Errors carry shell commands and public keys — single tokens hundreds of characters
   long. Without this they widen the whole page instead of wrapping. */
.fey-notice > div { min-width: 0; overflow-wrap: anywhere; }

/* ── Spinner ── */

.fey-spin {
    width: 14px;
    height: 14px;
    border: 1.5px solid var(--fey-primary-tint);
    border-top-color: var(--fey-primary);
    border-radius: 50%;
    animation: fey-spin 0.7s linear infinite;
    flex-shrink: 0;
}

.fey-spin-lg { width: 22px; height: 22px; border-width: 2px; }
@keyframes fey-spin { to { transform: rotate(360deg); } }

.fey-loading { display: flex; align-items: center; justify-content: center; gap: var(--s3); padding: var(--s8); color: var(--fey-ink-soft); font-size: 13px; }

/* ── Modal ── */

.fey-veil-layer {
    position: fixed;
    inset: 0;
    z-index: 60;
    background: var(--fey-veil);
    backdrop-filter: blur(3px);
    display: grid;
    place-items: center;
    padding: var(--s5);
    animation: fey-fade 0.18s var(--fey-ease-soft) both;
}

@keyframes fey-fade { from { opacity: 0; } to { opacity: 1; } }

.fey-modal {
    width: 100%;
    max-width: 460px;
    background: var(--fey-surface);
    border-radius: var(--fey-radius-lg);
    box-shadow: var(--fey-lift-lg);
    animation: fey-rise 0.28s var(--fey-ease) both;
    max-height: calc(100vh - var(--s7));
    display: flex;
    flex-direction: column;
}

.fey-modal-wide { max-width: 680px; }
.fey-modal-head { padding: var(--s5) var(--s5) var(--s3); }
.fey-modal-title { font-family: var(--fey-display); font-size: 21px; letter-spacing: -0.015em; }
.fey-modal-sub { font-size: 13px; color: var(--fey-ink-soft); margin-top: 4px; line-height: 1.55; }
.fey-modal-body { padding: var(--s3) var(--s5) var(--s5); overflow-y: auto; display: flex; flex-direction: column; gap: var(--s4); }

.fey-modal-foot {
    display: flex;
    justify-content: flex-end;
    gap: var(--s2);
    padding: var(--s4) var(--s5);
    border-top: 1px solid var(--fey-line);
}

/* ── Toast ── */

.fey-toasts {
    position: fixed;
    right: var(--s5);
    bottom: var(--s5);
    z-index: 90;
    display: flex;
    flex-direction: column;
    gap: var(--s2);
    max-width: 380px;
}

.fey-toast {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-ink);
    color: #fff;
    font-size: 13px;
    line-height: 1.5;
    box-shadow: var(--fey-lift-lg);
    animation: fey-toast-in 0.3s var(--fey-ease) both;
}

@keyframes fey-toast-in {
    from { opacity: 0; transform: translateY(10px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}

.fey-toast-good  { background: #256A4C; }
.fey-toast-error { background: #8E3535; }
.fey-toast-close { background: none; border: none; color: inherit; opacity: 0.6; cursor: pointer; padding: 0; line-height: 1; }
.fey-toast-close:hover { opacity: 1; }

/* ── Console ──
   Live deploy output. Monospace on dark, because that is what it is, and
   dressing it up as anything else helps nobody reading a stack trace. */

.fey-console {
    background: #211F2E;
    border-radius: var(--fey-radius-sm);
    padding: var(--s3) var(--s4);
    font-family: var(--fey-mono);
    font-size: 11.5px;
    line-height: 1.75;
    color: #C9C5DC;
    max-height: 300px;
    overflow-y: auto;
    white-space: pre-wrap;
    word-break: break-word;
}

.fey-console:empty::after { content: 'waiting…'; color: #6E6982; }

/* ── Copy field ── */

.fey-copy {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 7px 8px 7px 12px;
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-surface-sunken);
}

.fey-copy-value {
    flex: 1;
    min-width: 0;
    font-family: var(--fey-mono);
    font-size: 12px;
    color: var(--fey-ink-soft);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* ── Key/value list ── */

.fey-kv { display: grid; grid-template-columns: auto 1fr; gap: 9px var(--s5); font-size: 12.5px; align-items: baseline; }
.fey-kv dt { color: var(--fey-ink-faint); white-space: nowrap; }
.fey-kv dd { color: var(--fey-ink); text-align: right; font-variant-numeric: tabular-nums; }

/* ── Choice ──
   A radio button that is a whole row. Used where the option needs a second line
   of explanation to be choosable at all — picking a server means weighing free
   space and price, not reading a name. */

.fey-choice {
    display: flex;
    align-items: center;
    gap: var(--s3);
    width: 100%;
    padding: 11px 14px;
    border: 1px solid var(--fey-line-strong);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-surface);
    text-align: left;
    font: inherit;
    color: inherit;
    cursor: pointer;
    transition: border-color 0.16s var(--fey-ease-soft),
                background 0.16s var(--fey-ease-soft),
                box-shadow 0.16s var(--fey-ease-soft);
}

.fey-choice:hover { border-color: var(--fey-primary); }

.fey-choice.active {
    border-color: var(--fey-primary);
    background: var(--fey-primary-soft);
    box-shadow: var(--fey-ring);
}

/* ── Hosting choice ──
   The default answer to "where will it live", made large enough that it reads as
   an answer rather than as the first of several questions. The alternative below
   it is deliberately a line of text: it should be findable, not competing. */

.fey-host-primary {
    display: flex;
    align-items: center;
    gap: var(--s4);
    width: 100%;
    padding: var(--s4);
    border: 1px solid var(--fey-line-strong);
    border-radius: var(--fey-radius);
    background: var(--fey-surface);
    text-align: left;
    font: inherit;
    color: inherit;
    cursor: pointer;
    transition: border-color 0.16s var(--fey-ease-soft),
                background 0.16s var(--fey-ease-soft),
                box-shadow 0.16s var(--fey-ease-soft);
}

.fey-host-primary:hover { border-color: var(--fey-primary); }

.fey-host-primary.active {
    border-color: var(--fey-primary);
    background: linear-gradient(135deg, var(--fey-primary-soft), rgba(196, 144, 209, 0.06));
    box-shadow: var(--fey-ring);
}

.fey-host-mark {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    border-radius: var(--fey-radius-sm);
    background: var(--fey-primary-soft);
    flex-shrink: 0;
}

.fey-host-title { display: block; font-size: 14.5px; font-weight: 550; letter-spacing: -0.01em; }
.fey-host-note { display: block; font-size: 11.5px; color: var(--fey-ink-soft); margin-top: 1px; }

.fey-host-price {
    font-size: 12px;
    font-weight: 600;
    color: var(--fey-primary-deep);
    white-space: nowrap;
    flex-shrink: 0;
}

.fey-host-alt {
    display: flex;
    align-items: baseline;
    gap: var(--s2);
    flex-wrap: wrap;
    font-size: 12.5px;
    margin-top: calc(var(--s2) * -1);
}

/* A button that behaves like a link, for a secondary path that should not look like
   a second primary action. */
.fey-linkish {
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: 12.5px;
    color: var(--fey-primary-deep);
    cursor: pointer;
    text-decoration: none;
}

.fey-linkish:hover { text-decoration: underline; text-underline-offset: 2px; }

/* The address, shown while the name is being typed. Quiet, and directly under the
   field it is derived from. */
.fey-address-preview {
    display: flex;
    align-items: baseline;
    gap: var(--s2);
    padding: 9px 12px;
    border-radius: var(--fey-radius-sm);
    background: var(--fey-surface-sunken);
    border: 1px solid var(--fey-line);
    margin-top: calc(var(--s2) * -1);
    overflow: hidden;
}

.fey-address-preview .fey-mono {
    color: var(--fey-ink-soft);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The name is the one thing being typed here, so it gets room to be read back. */
.fey-input-lg { font-size: 16px; padding: 11px 13px; }

/* ── Segmented control ── */

.fey-seg { display: inline-flex; padding: 3px; background: var(--fey-surface-sunken); border: 1px solid var(--fey-line); border-radius: 9px; gap: 2px; }

.fey-seg-item {
    padding: 5px 13px;
    border: none;
    border-radius: 6px;
    background: transparent;
    font-size: 12.5px;
    font-weight: 500;
    color: var(--fey-ink-soft);
    cursor: pointer;
    transition: background 0.16s var(--fey-ease-soft), color 0.16s var(--fey-ease-soft);
}

.fey-seg-item:hover { color: var(--fey-ink); }
.fey-seg-item.active { background: var(--fey-surface); color: var(--fey-ink); box-shadow: var(--fey-lift); }

/* ── Auth ──
   A two-column page: a quiet canvas on the left that draws what Fey does, and
   the form on the right. The canvas is the only decorative surface in the app,
   and it earns its place by being the first thing anyone sees. */

.fey-auth { display: grid; grid-template-columns: 1.05fr 1fr; min-height: 100vh; }

.fey-auth-canvas {
    position: relative;
    overflow: hidden;
    padding: var(--s8) var(--s7);
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    background: linear-gradient(155deg, #F2EFFA 0%, #F8F7FC 55%, #FAF3FB 100%);
    border-right: 1px solid var(--fey-line);
}

.fey-auth-quote { max-width: 26ch; }

.fey-auth-quote h2 {
    font-family: var(--fey-display);
    font-size: 40px;
    line-height: 1.12;
    letter-spacing: -0.02em;
    color: var(--fey-ink);
}

.fey-auth-quote em { font-style: italic; color: var(--fey-primary-deep); }
.fey-auth-quote p { margin-top: var(--s4); font-size: 14px; color: var(--fey-ink-soft); line-height: 1.65; max-width: 34ch; }

/* The decoration: stacked bars standing in for slots on a server, drifting
   almost imperceptibly. It is the same object the Ship module renders for real,
   which is the point — the login page shows you what the product is. */
.fey-auth-slots { display: flex; flex-direction: column; gap: 7px; width: 260px; }

.fey-auth-slot {
    height: 13px;
    border-radius: 5px;
    background: rgba(139, 126, 200, 0.16);
    overflow: hidden;
    position: relative;
}

.fey-auth-slot span {
    position: absolute;
    inset: 0 auto 0 0;
    border-radius: 5px;
    background: linear-gradient(90deg, var(--fey-primary), var(--fey-accent));
    opacity: 0.55;
    animation: fey-breathe 7s var(--fey-ease-soft) infinite;
}

@keyframes fey-breathe {
    0%, 100% { transform: scaleX(1); }
    50%      { transform: scaleX(0.82); }
    transform-origin: left;
}

.fey-auth-slot span { transform-origin: left; }
.fey-auth-slot:nth-child(1) span { width: 72%; animation-delay: 0s; }
.fey-auth-slot:nth-child(2) span { width: 46%; animation-delay: 0.7s; }
.fey-auth-slot:nth-child(3) span { width: 88%; animation-delay: 1.5s; }
.fey-auth-slot:nth-child(4) span { width: 31%; animation-delay: 2.2s; }
.fey-auth-slot:nth-child(5) span { width: 60%; animation-delay: 3.0s; }

.fey-auth-panel { display: grid; place-items: center; padding: var(--s7) var(--s5); }
.fey-auth-form { width: 100%; max-width: 344px; display: flex; flex-direction: column; gap: var(--s4); }
.fey-auth-head { margin-bottom: var(--s1); }
.fey-auth-head h1 { font-family: var(--fey-display); font-size: 29px; letter-spacing: -0.02em; line-height: 1.15; }
.fey-auth-head p { margin-top: 6px; font-size: 13.5px; color: var(--fey-ink-soft); line-height: 1.55; }
.fey-auth-alt { font-size: 13px; color: var(--fey-ink-soft); text-align: center; }

/* The rules have to be visible or the "o" between them reads as a stray character
   rather than a separator, so this is one of the few places using the stronger line. */
.fey-auth-sep { display: flex; align-items: center; gap: var(--s3); color: var(--fey-ink-faint); font-size: 11.5px; }
.fey-auth-sep::before, .fey-auth-sep::after { content: ''; flex: 1; height: 1px; background: var(--fey-line-strong); }

@media (max-width: 860px) {
    .fey-auth { grid-template-columns: 1fr; }
    .fey-auth-canvas { display: none; }
}

/* ── The shape of a new project ──
   Shown as what you get, not as a name: the three stages side by side with what each
   one holds. Someone who has never heard the word "staging" can read this. */
.fey-shape {
    display: flex;
    flex-direction: column;
    gap: var(--s3);
    padding: var(--s3) var(--s4);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-primary-soft);
}

.fey-shape-stages { display: flex; gap: var(--s2); }

.fey-shape-stage {
    flex: 1;
    min-width: 0;
    padding: var(--s2) var(--s3);
    border-radius: 7px;
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
}

.fey-shape-stage-name {
    font-size: 12px;
    font-weight: 550;
    margin-bottom: 1px;
}

@media (max-width: 560px) {
    .fey-shape-stages { flex-direction: column; }
}

/* ── Stages on the Ship page ──
   A quiet band per stage rather than a card around one: the slots are the objects and
   the stage is only where they sit. A border would compete with them for attention. */
.fey-stage { display: flex; flex-direction: column; gap: var(--s3); }

.fey-stage-head {
    display: flex;
    align-items: baseline;
    gap: var(--s3);
    padding-bottom: var(--s2);
    border-bottom: 1px solid var(--fey-line);
}

.fey-stage-name {
    font-family: var(--fey-display);
    font-size: 16px;
    letter-spacing: -0.01em;
    color: var(--fey-ink);
}

/* ── A quiet line that opens ──
   For everything a dialog should answer by itself. Reads as one row with what it
   decided on the right, so it can be checked without being opened. */
.fey-disclose {
    display: flex;
    align-items: baseline;
    gap: var(--s3);
    width: 100%;
    padding: 7px 0;
    background: none;
    border: none;
    border-top: 1px solid var(--fey-line);
    color: var(--fey-ink-soft);
    font: inherit;
    font-size: 12.5px;
    text-align: left;
    cursor: pointer;
    transition: color 0.15s var(--fey-ease-soft);
}

.fey-disclose:hover { color: var(--fey-ink); }
.fey-disclose > .fey-faint { margin-left: auto; }
.fey-disclose-caret { font-size: 10px; opacity: 0.55; }

/* ── The board ──
   Columns are stages, cards are slots, and both are things a person arranges. It
   scrolls sideways rather than wrapping: a pipeline reads left to right and folding
   it onto a second line breaks the one thing the layout is for. */
.fey-board {
    display: flex;
    align-items: flex-start;
    gap: var(--s3);
    overflow-x: auto;
    padding-bottom: var(--s4);
}

.fey-board-col {
    flex: 0 0 268px;
    display: flex;
    flex-direction: column;
    gap: var(--s2);
    padding: var(--s3);
    border-radius: var(--fey-radius);
    background: var(--fey-surface-sunken);
    border: 1px solid transparent;
    transition: border-color 0.16s var(--fey-ease-soft), background 0.16s var(--fey-ease-soft);
}

/* The column under the cursor while something is being dragged. Without it a drop is a
   guess, and a guess about where a slot lands is not a nice guess to have to make. */
.fey-board-col.over {
    border-color: var(--fey-primary);
    background: var(--fey-primary-soft);
}

.fey-board-col.loose { background: transparent; border-style: dashed; border-color: var(--fey-line); }
.fey-board-col.add { background: none; flex: 0 0 190px; }

.fey-board-head {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 0 2px var(--s2);
}

.fey-board-name {
    background: none;
    border: none;
    padding: 0;
    font-family: var(--fey-display);
    font-size: 15px;
    letter-spacing: -0.01em;
    color: var(--fey-ink);
    cursor: text;
    text-align: left;
}

.fey-board-name:hover { color: var(--fey-primary-deep); }

.fey-board-x {
    margin-left: auto;
    background: none;
    border: none;
    color: var(--fey-ink-faint);
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    opacity: 0;
    transition: opacity 0.16s var(--fey-ease-soft), color 0.16s var(--fey-ease-soft);
}

.fey-board-col:hover .fey-board-x { opacity: 1; }
.fey-board-x:hover { color: var(--fey-red); }

.fey-board-cards { display: flex; flex-direction: column; gap: var(--s2); min-height: 8px; }

.fey-board-empty {
    padding: var(--s5) var(--s3);
    border: 1px dashed var(--fey-line);
    border-radius: var(--fey-radius-sm);
    text-align: center;
    font-size: 11.5px;
    color: var(--fey-ink-faint);
}

.fey-board-add-card,
.fey-board-add-col {
    width: 100%;
    padding: 7px;
    background: none;
    border: 1px dashed var(--fey-line);
    border-radius: var(--fey-radius-sm);
    color: var(--fey-ink-faint);
    font: inherit;
    font-size: 12px;
    cursor: pointer;
    transition: color 0.16s var(--fey-ease-soft), border-color 0.16s var(--fey-ease-soft);
}

.fey-board-add-card:hover,
.fey-board-add-col:hover { color: var(--fey-primary-deep); border-color: var(--fey-line-strong); }
.fey-board-add-col { padding: var(--s4) var(--s3); }

/* ── A slot as a card ── */
.fey-slot-card {
    display: flex;
    flex-direction: column;
    gap: 5px;
    padding: var(--s3);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    box-shadow: var(--fey-shadow-sm, 0 1px 2px rgba(45, 42, 62, 0.04));
    color: inherit;
    text-decoration: none;
    cursor: grab;
    transition: border-color 0.16s var(--fey-ease-soft), transform 0.16s var(--fey-ease-soft);
}

.fey-slot-card:hover {
    border-color: var(--fey-line-strong);
    text-decoration: none;
    transform: translateY(-1px);
}

.fey-slot-card:active { cursor: grabbing; }

.fey-slot-card-head { display: flex; align-items: center; gap: var(--s2); }
.fey-slot-card-name { font-size: 13px; font-weight: 550; }

.fey-slot-card-url {
    font-size: 10.5px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fey-slot-card-error {
    font-size: 10.5px;
    color: var(--fey-red);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fey-input-sm { padding: 5px 8px; font-size: 12.5px; }

/* ── The road to live, read ──
   One row per stage, top to bottom, from where the work starts to where it lives.
   No slots on it: a publish moves the whole stage by rule, so the thing this view
   talks about is the project. Deliberately plainer than the board — there is
   nothing here to rearrange, and the slots are one switch away. */
.fey-road {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius);
    background: var(--fey-surface);
    overflow: hidden;
}

.fey-road-step {
    display: flex;
    align-items: center;
    gap: var(--s4);
    padding: var(--s4) var(--s5);
    border-top: 1px solid var(--fey-line);
}

.fey-road-step:first-child { border-top: none; }

/* Filled only where something is actually being served, so the eye finds how far
   down the road this project has got without reading a word. */
.fey-road-mark {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
    border: 1.5px solid var(--fey-line-strong);
}

.fey-road-mark.on { background: var(--fey-green); border-color: var(--fey-green); }

.fey-road-body {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.fey-road-name {
    font-family: var(--fey-display);
    font-size: 16px;
    letter-spacing: -0.01em;
}

.fey-road-state {
    display: flex;
    align-items: baseline;
    gap: 6px;
    flex-wrap: wrap;
    font-size: 11.5px;
    color: var(--fey-ink-soft);
}

.fey-road-hint { font-size: 11px; color: var(--fey-ink-faint); }
.fey-road-hint a { color: var(--fey-ink-soft); }

.fey-road-actions {
    display: flex;
    align-items: center;
    gap: var(--s3);
    flex-shrink: 0;
}

.fey-road-actions .fey-publish-note { white-space: nowrap; }

/* Whatever is on nobody's road to live. A line, not a grid of cards. */
.fey-road-loose {
    margin-top: var(--s4);
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    font-size: 11.5px;
    color: var(--fey-ink-faint);
    cursor: pointer;
    text-decoration: underline;
    text-decoration-color: var(--fey-line-strong);
    text-underline-offset: 3px;
}

.fey-road-loose:hover { color: var(--fey-ink-soft); }

@media (max-width: 720px) {
    .fey-road-step { flex-wrap: wrap; }
    .fey-road-actions { width: 100%; justify-content: flex-end; }
}

.fey-pipeline-slot {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 7px var(--s3);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-sm);
    color: inherit;
    text-decoration: none;
    transition: border-color 0.16s var(--fey-ease-soft);
}

.fey-pipeline-slot:hover { border-color: var(--fey-line-strong); text-decoration: none; }

/* ── The rule at the foot of a column ── */
.fey-board-rule {
    display: flex;
    flex-direction: column;
    gap: 3px;
    padding-top: var(--s2);
    margin-top: 2px;
    border-top: 1px solid var(--fey-line);
}

.fey-select-sm { padding: 4px 7px; font-size: 11.5px; }

/* ── The machines panel ──
   One row per droplet, four numbers each. The comparison is the point, so the rows
   share a grid rather than each sizing itself to its own contents. */
.fey-machine-name {
    font-family: var(--fey-display);
    font-size: 16px;
    letter-spacing: -0.01em;
    color: inherit;
    text-decoration: none;
}

.fey-machine-name:hover { color: var(--fey-primary-deep); text-decoration: none; }

.fey-machine-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--s4);
}

.fey-machine-metric {
    display: flex;
    flex-direction: column;
    gap: 2px;
    min-width: 0;
}

.fey-machine-now {
    font-family: var(--fey-display);
    font-size: 22px;
    line-height: 1.1;
    letter-spacing: -0.01em;
}

/* ── A line of history ── */
.fey-spark {
    width: 100%;
    height: 24px;
    margin-top: var(--s2);
    display: block;
    overflow: visible;
}

.fey-spark-ink { color: var(--fey-primary); }

/* ── The drive: the files a slot serves ──
   A list and not a grid of thumbnails. What somebody does here is find a file by its
   name and check when it changed, and a wall of squares makes both harder. */
.fey-drive { display: flex; flex-direction: column; }

.fey-drive-row {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: 7px var(--s2);
    border-top: 1px solid var(--fey-line);
}

.fey-drive-row:first-child { border-top: none; }
.fey-drive-row:hover { background: var(--fey-surface-sunken); }

.fey-drive-name {
    display: flex;
    align-items: center;
    gap: var(--s2);
    flex: 1;
    min-width: 0;
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    font-size: 12.5px;
    color: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.fey-drive-name:hover { color: var(--fey-primary-deep); text-decoration: none; }
.fey-drive-icon { font-size: 13px; flex-shrink: 0; }
.fey-drive-meta { font-size: 11px; white-space: nowrap; flex-shrink: 0; }

.fey-crumbs { align-items: baseline; }

.fey-crumb {
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    font-size: 12.5px;
    color: var(--fey-ink-soft);
    cursor: pointer;
}

.fey-crumb:hover { color: var(--fey-ink); }
.fey-crumb.on { color: var(--fey-ink); font-weight: 550; cursor: default; }

/* ── Tabs: the questions a page answers ──
   One strip, one word each. A switch works while there are two things; the moment
   there is a third it has to become a list, and a list of three reads faster than a
   toggle plus a button anyway. */
.fey-tabs {
    display: inline-flex;
    align-items: center;
    gap: 2px;
    padding: 3px;
    border: 1px solid var(--fey-line);
    border-radius: 999px;
    background: var(--fey-surface-sunken);
}

.fey-tab {
    padding: 5px var(--s4);
    border: none;
    border-radius: 999px;
    background: none;
    font: inherit;
    font-size: 12.5px;
    color: var(--fey-ink-soft);
    cursor: pointer;
    white-space: nowrap;
    transition: background 0.16s var(--fey-ease-soft), color 0.16s var(--fey-ease-soft);
}

.fey-tab:hover { color: var(--fey-ink); }

.fey-tab.on {
    background: var(--fey-surface);
    color: var(--fey-primary-deep);
    font-weight: 550;
    box-shadow: 0 1px 2px rgba(45, 42, 62, 0.06);
}

/* The second row: which slot, rather than which question. Squarer and quieter, so the
   two strips never read as the same kind of choice. */
.fey-tabs.sub {
    display: flex;
    flex-wrap: wrap;
    border-radius: var(--fey-radius-sm);
    background: none;
    border: none;
    padding: 0;
    gap: var(--s1);
}

.fey-tabs.sub .fey-tab {
    border-radius: var(--fey-radius-sm);
    font-size: 12px;
    font-family: var(--fey-mono);
    border: 1px solid transparent;
}

.fey-tabs.sub .fey-tab.on {
    border-color: var(--fey-line-strong);
    background: var(--fey-surface);
}

/* ── A switch that reads as one ── */
.fey-toggle {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 6px var(--s3);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-sm);
    font: inherit;
    font-size: 12.5px;
    background: none;
    color: var(--fey-ink-soft);
    cursor: pointer;
    user-select: none;
    transition: border-color 0.16s var(--fey-ease-soft), background 0.16s var(--fey-ease-soft),
                color 0.16s var(--fey-ease-soft);
}

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

.fey-toggle.on {
    border-color: var(--fey-primary);
    background: var(--fey-primary-soft);
    color: var(--fey-primary-deep);
}

.fey-toggle-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--fey-ink-faint);
    transition: background 0.16s var(--fey-ease-soft);
}

.fey-toggle.on .fey-toggle-dot { background: var(--fey-primary); }

/* -- Publish, on the arrow --
   The verb sits on the rule that allows it. A button anywhere else would leave the
   reader working out which two stages it meant. */
/* The button that moves a stage on. Named after where it lands, and the only
   thing on the right of its row, so it gets to be comfortable. */
.fey-publish {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px var(--s4);
    background: var(--fey-surface);
    border: 1px solid var(--fey-line-strong);
    border-radius: 999px;
    color: var(--fey-primary-deep);
    font: inherit;
    font-size: 12.5px;
    font-weight: 550;
    white-space: nowrap;
    cursor: pointer;
    box-shadow: 0 1px 2px rgba(45, 42, 62, 0.05);
    transition: background 0.16s var(--fey-ease-soft), border-color 0.16s var(--fey-ease-soft),
                transform 0.16s var(--fey-ease-soft);
}

.fey-publish:hover:not(:disabled) {
    background: var(--fey-primary-soft);
    border-color: var(--fey-primary);
    transform: translateY(-1px);
}

.fey-publish:disabled {
    color: var(--fey-ink-faint);
    border-color: var(--fey-line);
    box-shadow: none;
    cursor: default;
}

.fey-publish-arrow { font-size: 14px; line-height: 1; }

.fey-publish-note { font-size: 10.5px; color: var(--fey-ink-soft); }
.fey-publish-note.faint { color: var(--fey-ink-faint); }

.fey-promote-row {
    display: flex;
    align-items: center;
    gap: var(--s2);
    padding: 6px var(--s3);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-sm);
    font-size: 12px;
}

.fey-promote-row.blocked { border-style: dashed; color: var(--fey-ink-soft); }

/* A project whose slots are being taken off their machines. Dimmed and inert rather
   than gone: it is still there, and the work on it is real and takes a minute. */
.fey-card-going {
    opacity: 0.55;
    pointer-events: none;
}

/* A row of the environment editor. Wraps as a unit so a narrow window stacks the
   fields instead of pushing the controls past the edge. */
.fey-env-row { width: 100%; align-items: center; }

/* A name you can click to change. Deliberately not a button until you hover it: the name is
   what the card is, and dressing it as a control every time would make the page noisier than
   the thing it names. */
.fey-rename {
    padding: 0;
    background: none;
    border: none;
    border-bottom: 1px dashed transparent;
    font: inherit;
    color: inherit;
    cursor: text;
    text-align: left;
}

.fey-rename:hover { border-bottom-color: var(--fey-line-strong, var(--fey-line)); }

/* ── A card on the feedback board ──
   Lighter than a slot card, because there are going to be a lot more of them and none of them
   has a status to report. Grab-shaped, since dragging one is the point. */
.fey-fb-card {
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-sm);
    padding: var(--s3);
    cursor: grab;
    transition: border-color 120ms ease, box-shadow 120ms ease;
}

.fey-fb-card:hover { border-color: var(--fey-primary); }
.fey-fb-card:active { cursor: grabbing; }

.fey-fb-title { font-size: 12.5px; font-weight: 550; line-height: 1.45; }

.fey-fb-body {
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--fey-ink-soft);
    margin-top: 3px;
    white-space: pre-wrap;
}

/* Who wrote it, so whoever reads it in two weeks knows who to ask. */
.fey-fb-foot {
    display: flex;
    align-items: center;
    gap: 5px;
    margin-top: var(--s3);
    min-width: 0;
}

.fey-fb-foot .fey-faint { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.fey-fb-new { display: flex; flex-direction: column; gap: var(--s2); padding: var(--s2) 0; }

/* ── The first minute ──
   A project nobody has asked anything of. There is no state to report and nothing to configure,
   so there is one box in the middle of an empty room. Everything else on this screen would be
   furniture. */
.fey-first {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: calc(100vh - 40px);
    padding: var(--s6);
}

.fey-first-inner { width: 100%; max-width: 620px; text-align: center; }

.fey-first-title { font-size: 30px; margin: 0 0 var(--s3); }

.fey-first-sub {
    color: var(--fey-ink-soft);
    font-size: 14px;
    margin: 0 0 var(--s6);
    line-height: 1.6;
}

.fey-first-foot {
    color: var(--fey-ink-faint);
    font-size: 11.5px;
    margin: var(--s4) 0 0;
}

/* ── The composer ──
   The only control on the empty screen, so it is allowed to be the largest thing on it. */
.fey-composer {
    display: flex;
    align-items: flex-end;
    gap: var(--s3);
    padding: var(--s3);
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius);
    box-shadow: var(--fey-shadow-sm, 0 1px 2px rgba(20,16,40,0.04));
    text-align: left;
}

.fey-composer:focus-within { border-color: var(--fey-primary); }

.fey-composer-big { padding: var(--s4); }

.fey-composer-input {
    flex: 1;
    min-width: 0;
    border: none;
    background: none;
    resize: none;
    font: inherit;
    font-size: 14px;
    line-height: 1.6;
    color: var(--fey-ink);
    outline: none;
}

.fey-composer-input::placeholder { color: var(--fey-ink-faint); }

.fey-composer-wrap {
    padding: var(--s4);
    border-top: 1px solid var(--fey-line);
    background: var(--fey-bg);
}

/* ── The split ──
   Conversation and site, one bar above both. Not one bar per pane: three stacked bars before the
   first message is what this screen exists to not be. */
.fey-work { display: flex; flex-direction: column; height: 100vh; min-height: 0; }

.fey-work-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s4);
    padding: var(--s3) var(--s5);
    border-bottom: 1px solid var(--fey-line);
    background: var(--fey-surface);
    flex: 0 0 auto;
}

/* ── Ship's road ──
   Cards side by side with the arrows between them, because that is the shape of the thing: a
   version moves left to right and arrives at the people who use it. The vertical list this
   replaced was accurate and unreadable — five buttons on every row, and never the one somebody
   came for.

   A card is narrow on purpose. Three of them have to sit in the width of the page, and the
   discipline that forces — one figure, one date, one line of state — is what makes the road
   readable at a glance rather than something you audit. */

.fey-road-rail { display: flex; align-items: stretch; }

.fey-lane {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    padding: var(--s4) var(--s4) var(--s3);
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-lg);
    box-shadow: var(--fey-lift);
}

.fey-lane-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s3); }
.fey-lane-name { font-size: 13px; color: var(--fey-ink-soft); }

/* The far end of the road, which is the one people are really asking about. */
.fey-lane.on .fey-lane-name { color: var(--fey-ink); font-weight: 500; }

.fey-ver {
    margin: 0;
    font-family: var(--fey-mono);
    font-size: 26px;
    font-weight: 500;
    line-height: 1;
    letter-spacing: -0.02em;
}
.fey-when { margin: var(--s1) 0 var(--s4); font-size: 12.5px; color: var(--fey-ink-faint); }

.fey-state {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    margin: 0 0 var(--s4);
    font-size: 12.5px;
    color: var(--fey-ink-soft);
}

/* Hollow rather than grey: grey on a card this quiet reads as disabled, and a resting stage
   is not broken — it comes back the moment somebody opens it. */
.fey-dot-rest { background: transparent; border: 1.5px solid var(--fey-ink-faint); }

.fey-lane-foot { margin-top: auto; display: flex; align-items: baseline; justify-content: space-between; gap: var(--s3); }
.fey-lane-open {
    font-size: 13px;
    color: var(--fey-primary-deep);
    text-decoration: none;
    border-bottom: 1px solid var(--fey-line-strong);
    padding-bottom: 1px;
}
.fey-lane-open:hover { border-color: var(--fey-primary); }
.fey-lane-host { font-size: 11px; color: var(--fey-ink-faint); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* The arrow between two cards is the publish. It is drawn as an arrow and not as a button
   because what it does is already the only thing an arrow between two stages could mean. */
.fey-tick {
    flex: 0 0 34px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--fey-ink-faint);
    font-size: 15px;
}
.fey-tick-go {
    font: inherit;
    font-size: 15px;
    line-height: 1;
    background: none;
    border: 0;
    border-radius: 999px;
    width: 28px;
    height: 28px;
    color: var(--fey-ink-faint);
    cursor: pointer;
    transition: background 0.14s var(--fey-ease-soft), color 0.14s var(--fey-ease-soft);
}
.fey-tick-go:hover:not(:disabled) { background: var(--fey-primary-tint); color: var(--fey-primary-deep); }
.fey-tick-go:disabled { cursor: default; opacity: .45; }

/* ── The ••• and what it hides ── */

.fey-more { position: relative; }
.fey-more-btn {
    font: inherit;
    line-height: 1;
    letter-spacing: 0.12em;
    background: none;
    border: 0;
    padding: 4px 6px;
    border-radius: 6px;
    color: var(--fey-ink-faint);
    cursor: pointer;
}
.fey-more-btn:hover { background: var(--fey-paper); color: var(--fey-ink); }

/* A sheet of nothing behind the menu, so a click anywhere closes it without the page having to
   listen to the document. */
.fey-menu-veil { position: fixed; inset: 0; z-index: 40; }

.fey-menu {
    position: absolute;
    right: 0;
    top: calc(100% + 6px);
    z-index: 41;
    min-width: 200px;
    padding: 5px;
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-sm);
    box-shadow: var(--fey-lift-lg);
}
.fey-menu button, .fey-menu a {
    display: block;
    width: 100%;
    text-align: left;
    font: inherit;
    font-size: 13.5px;
    background: none;
    border: 0;
    padding: 7px 10px;
    border-radius: 6px;
    color: var(--fey-ink);
    text-decoration: none;
    cursor: pointer;
}
.fey-menu button:hover, .fey-menu a:hover { background: var(--fey-paper); }
.fey-menu button:disabled { color: var(--fey-ink-faint); background: none; cursor: default; }
.fey-menu button.warn { color: var(--fey-red); }
.fey-menu hr { border: 0; border-top: 1px solid var(--fey-line); margin: 5px 0; }

/* ── What is not live yet ── */

.fey-banner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s5);
    flex-wrap: wrap;
    margin-bottom: var(--s4);
    padding: var(--s4) var(--s5);
    background: var(--fey-primary-soft);
    border: 1px solid var(--fey-line-strong);
    border-radius: var(--fey-radius-lg);
}
.fey-banner h2 { margin: 0; font-size: 16px; font-weight: 500; color: var(--fey-primary-deep); }
.fey-banner p { margin: 3px 0 0; font-size: 13.5px; color: var(--fey-primary-deep); opacity: .8; }

/* The rule, read once, at the foot — where a sentence that never changes belongs. */
.fey-note { margin: var(--s5) 0 0; max-width: 62ch; font-size: 13px; color: var(--fey-ink-faint); }
.fey-note a { color: var(--fey-primary-deep); }

/* Ship's tabs are the segmented control, rounded the whole way. */
.fey-seg-round, .fey-seg-round .fey-seg-item { border-radius: 999px; }

@media (max-width: 900px) {
    /* Three cards do not fit, so the road stands up and the arrows turn with it. */
    .fey-road-rail { flex-direction: column; }
    .fey-tick { flex: 0 0 28px; transform: rotate(90deg); }
}

.fey-work-name {
    font-family: var(--fey-display);
    font-size: 16px;
    color: var(--fey-ink);
    text-decoration: none;
}

.fey-work-name:hover { color: var(--fey-primary-deep); }

.fey-work-split {
    display: grid;
    grid-template-columns: minmax(320px, 42%) 5px minmax(0, 1fr);
    flex: 1;
    min-height: 0;
}

/* The grip is the device picker. Dragging it gives every width somebody could want, which three
   buttons labelled phone, tablet and desktop never do.

   Five pixels is a hard thing to hit with a mouse, so the strip is the target and the line
   inside it is what you see. touch-action none, or the browser treats the drag as a scroll and
   the divider never moves on a trackpad. */
.fey-work-grip {
    display: flex;
    align-items: stretch;
    justify-content: center;
    background: none;
    cursor: col-resize;
    touch-action: none;
    user-select: none;
}

.fey-work-grip-line {
    width: 1px;
    background: var(--fey-line);
    transition: background 120ms ease, width 120ms ease;
}

.fey-work-grip:hover .fey-work-grip-line,
.fey-dragging .fey-work-grip-line { width: 3px; background: var(--fey-primary); }

/* While dragging, the iframe must not eat the pointer — which it does the moment the cursor
   crosses into it, ending the drag halfway across the screen. */
.fey-dragging { cursor: col-resize; user-select: none; }
.fey-dragging iframe { pointer-events: none; }

.fey-work-chat {
    display: flex;
    flex-direction: column;
    min-width: 0;
    min-height: 0;
    background: var(--fey-surface);
}

.fey-work-preview { min-width: 0; min-height: 0; background: var(--fey-bg); }

/* What the preview sits in. At desktop it is the whole pane; at the two smaller widths the
   frame narrows and centres, and the pane around it goes darker so the edges of the "device"
   are visible — otherwise a narrow site on a white background just looks like a narrow site. */
.fey-preview-stage {
    width: 100%;
    height: 100%;
    display: flex;
    justify-content: center;
}

.fey-preview-tablet, .fey-preview-mobile {
    background: var(--fey-ink-faint);
    padding: var(--s4) 0;
}

.fey-preview-tablet .fey-preview-frame { width: min(820px, 100%); }
.fey-preview-mobile .fey-preview-frame { width: min(390px, 100%); }

.fey-preview-tablet .fey-preview-frame,
.fey-preview-mobile .fey-preview-frame {
    border-radius: var(--fey-radius);
    background: #fff;
    box-shadow: 0 6px 24px rgba(20, 16, 40, 0.18);
}

.fey-preview-frame {
    width: 100%;
    height: 100%;
    border: none;
    display: block;
    transition: width 160ms var(--fey-ease-soft);
}

.fey-icon-btn svg { width: 14px; height: 14px; }

@media (max-width: 860px) {
    .fey-work-split { grid-template-columns: minmax(0, 1fr); }
    .fey-work-grip, .fey-work-preview { display: none; }
}

/* ── Messages ── */
.fey-messages {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--s5);
    display: flex;
    flex-direction: column;
    gap: var(--s5);
}

.fey-msg-who {
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    color: var(--fey-ink-faint);
    margin-bottom: 4px;
}

.fey-msg-body { font-size: 13.5px; line-height: 1.65; white-space: pre-wrap; }

.fey-msg-fey .fey-msg-body { color: var(--fey-ink-soft); }

/* ── What is being built ──
   The whole plan from the first second, greyed out, filling in with the seconds each step took.
   A spinner says "wait". This says what is being done on your behalf. */
.fey-steps {
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius);
    padding: var(--s4);
    background: var(--fey-bg);
}

.fey-steps-head {
    display: flex;
    align-items: center;
    gap: var(--s3);
    font-size: 13px;
    font-weight: 550;
    margin-bottom: var(--s3);
}

.fey-steps-tick { color: var(--fey-green, #2f9e6e); }

.fey-step {
    display: flex;
    align-items: center;
    gap: var(--s3);
    padding: 3px 0;
    font-size: 12.5px;
    flex-wrap: wrap;
}

.fey-step-mark { width: 14px; display: inline-flex; justify-content: center; }
.fey-step-label { flex: 1; min-width: 0; }
.fey-step-ms { font-family: var(--fey-mono); font-size: 10.5px; color: var(--fey-ink-faint); }

.fey-step-pending { color: var(--fey-ink-faint); }
.fey-step-running { color: var(--fey-primary-deep); font-weight: 550; }
.fey-step-done .fey-step-mark { color: var(--fey-green, #2f9e6e); }
.fey-step-failed { color: var(--fey-red, #c2554b); }

.fey-step-error {
    width: 100%;
    margin-left: 22px;
    font-family: var(--fey-mono);
    font-size: 10.5px;
    white-space: pre-wrap;
}

.fey-ring {
    width: 13px;
    height: 13px;
    border: 2px solid var(--fey-primary-soft);
    border-top-color: var(--fey-primary);
    border-radius: 50%;
    animation: fey-spin 0.8s linear infinite;
    display: inline-block;
}

.fey-ring-sm { width: 10px; height: 10px; border-width: 2px; }

@keyframes fey-spin { to { transform: rotate(360deg); } }

/* One line, above the composer, for the only thing worth interrupting for. */
.fey-work-publish {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s3);
    font-size: 12.5px;
    color: var(--fey-ink-soft);
    margin-bottom: var(--s3);
}

/* A control that is an icon and nothing else. */
.fey-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-surface);
    color: var(--fey-ink-soft);
    font-size: 13px;
    text-decoration: none;
    cursor: pointer;
}

.fey-icon-btn:hover:not(:disabled) { border-color: var(--fey-primary); color: var(--fey-ink); }
.fey-icon-btn:disabled { opacity: 0.4; cursor: default; }

.fey-input-sm { padding: 4px 8px; font-size: 12px; }

/* ── Somebody's face ──
   A photo when there is one, and otherwise their initial in the colour their account was given.
   Never a grey silhouette: a generated identity says who this is, and the silhouette says the
   picture failed to load. */
.fey-face {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    overflow: hidden;
}

.fey-face-initial {
    color: #fff;
    font-family: var(--fey-display);
    font-weight: 500;
    line-height: 1;
    letter-spacing: 0;
}

/* ── A profile ── */
.fey-profile-head {
    display: flex;
    align-items: flex-start;
    gap: var(--s5);
    flex-wrap: wrap;
    padding: var(--s5);
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius);
}

.fey-profile-bio {
    margin: var(--s3) 0 0;
    font-size: 13.5px;
    line-height: 1.65;
    max-width: 62ch;
    white-space: pre-wrap;
}

/* A figure you can press to see who is behind it. Looks like the others until you hover. */
.fey-stat-btn {
    display: block;
    width: 100%;
    padding: 0;
    border: none;
    background: none;
    font: inherit;
    color: inherit;
    text-align: left;
    cursor: pointer;
}

.fey-card-on { border-color: var(--fey-primary); }

.fey-grid-4 { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }

/* A message nobody has opened. One line at the edge rather than a background wash, which on a
   list of five unread turns the page into a block of colour. */
.fey-unread { box-shadow: inset 2px 0 0 var(--fey-primary); padding-left: var(--s3); }

/* ── Looking inside a database ──
   Tables down one side, rows in the rest. The list is narrow and fixed because a table name is
   short and the grid is the thing that needs every pixel. */
.fey-browser {
    display: grid;
    grid-template-columns: 220px minmax(0, 1fr);
    gap: var(--s5);
    align-items: start;
}

@media (max-width: 760px) {
    .fey-browser { grid-template-columns: minmax(0, 1fr); }
}

.fey-browser-side {
    display: flex;
    flex-direction: column;
    gap: 2px;
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius);
    padding: var(--s3);
    max-height: 70vh;
    overflow-y: auto;
}

.fey-browser-main {
    background: var(--fey-surface);
    border: 1px solid var(--fey-line);
    border-radius: var(--fey-radius);
    padding: var(--s5);
    min-width: 0;
}

.fey-table-item {
    display: flex;
    flex-direction: column;
    gap: 1px;
    padding: 6px 8px;
    border: none;
    border-radius: var(--fey-radius-sm);
    background: none;
    font: inherit;
    text-align: left;
    color: var(--fey-ink-soft);
    cursor: pointer;
}

.fey-table-item:hover { background: var(--fey-bg); color: var(--fey-ink); }

.fey-table-item-on {
    background: var(--fey-primary-soft);
    color: var(--fey-primary-deep);
}

/* A header you can press to sort by it. Looks like a header until you need it to be a button. */
.fey-sort {
    padding: 0;
    background: none;
    border: none;
    font: inherit;
    color: inherit;
    cursor: pointer;
    white-space: nowrap;
}

.fey-sort:hover { color: var(--fey-primary-deep); }

/* Rows of somebody's real data, so: monospace, tight, and never wrapping. A grid that reflows
   as values get longer is one where the eye loses the column it was following. */
.fey-grid-table td { font-family: var(--fey-mono); font-size: 11.5px; white-space: nowrap; }
.fey-grid-table th { vertical-align: bottom; }

.fey-cell { display: inline-block; max-width: 340px; overflow: hidden; text-overflow: ellipsis; }

/* NULL is a fact, and an empty cell is a different one. */
.fey-null { color: var(--fey-ink-faint); font-style: italic; opacity: 0.7; }

/* One slot and what can be done to it. A line rather than a card each: seven slots as seven
   cards is a page you scroll, and the whole point of listing them together is seeing them at
   once. The rule between rows is what keeps a name from reading as the line above's detail. */
.fey-data-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--s4);
    flex-wrap: wrap;
    padding: var(--s4) 0;
    border-top: 1px solid var(--fey-line);
}

.fey-data-row:first-child { border-top: none; padding-top: 0; }
.fey-data-row:last-child { padding-bottom: 0; }
.fey-env-row .fey-check { flex-shrink: 0; }

/* ── Prose ──
   Rendered from Markdown, so the styling has to reach elements no component wrote.
   Measured rather than full-width: a line of body text past about 75 characters is
   one the eye loses on the way back. */
.fey-prose { max-width: 72ch; color: var(--fey-ink); font-size: 14px; line-height: 1.7; }

/* What holds prose: the measure plus the padding around it, so the card ends where the
   text does. Wider than the 72ch inside on purpose — a block of code is allowed the
   whole card, and it is the one thing here that wants every pixel it can get. */
.fey-reading { max-width: 700px; }

.fey-prose > *:first-child { margin-top: 0; }
.fey-prose > *:last-child { margin-bottom: 0; }

.fey-prose h1 {
    font-family: var(--fey-display);
    font-size: 26px;
    letter-spacing: -0.02em;
    margin: 0 0 var(--s5);
}

.fey-prose h2 {
    font-family: var(--fey-display);
    font-size: 18px;
    letter-spacing: -0.01em;
    margin: var(--s7) 0 var(--s3);
    padding-top: var(--s4);
    border-top: 1px solid var(--fey-line);
}

.fey-prose p { margin: 0 0 var(--s4); }
.fey-prose strong { font-weight: 600; }

.fey-prose ul { margin: 0 0 var(--s4); padding-left: var(--s5); list-style: disc; }
.fey-prose ol { margin: 0 0 var(--s4); padding-left: var(--s5); list-style: decimal; }
.fey-prose li { margin-bottom: 6px; }
.fey-prose li::marker { color: var(--fey-ink-faint); }

.fey-prose code {
    font-family: var(--fey-mono);
    font-size: 12.5px;
    padding: 1px 5px;
    border-radius: 5px;
    background: var(--fey-primary-soft);
    color: var(--fey-primary-deep);
}

/* A block scrolls sideways rather than wrapping: a command broken across lines is a
   command somebody pastes wrong. */
.fey-prose pre {
    margin: 0 0 var(--s4);
    padding: var(--s4);
    border-radius: var(--fey-radius-sm);
    background: var(--fey-ink);
    overflow-x: auto;
}

.fey-prose pre code {
    background: none;
    color: #E9E7F2;
    padding: 0;
    font-size: 12px;
    white-space: pre;
}

/* ── The next step ──
   One line with the button that does it. Tinted by how much it matters and never
   loud: a page that shouts at every state teaches people to stop reading it. */
.fey-next {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s5);
    padding: var(--s4) var(--s5);
    border-radius: var(--fey-radius);
    border: 1px solid var(--fey-line);
    background: var(--fey-surface);
}

.fey-next-title { font-size: 14px; font-weight: 550; }

.fey-next.good { border-color: rgba(74, 158, 116, 0.28); background: rgba(74, 158, 116, 0.05); }
.fey-next.ready { border-color: var(--fey-primary); background: var(--fey-primary-soft); }
.fey-next.warn { border-color: rgba(197, 143, 62, 0.35); background: rgba(197, 143, 62, 0.06); }
.fey-next.busy { border-style: dashed; }

@media (max-width: 640px) {
    .fey-next { flex-direction: column; align-items: stretch; }
}

/* ── Packages ──
   A column of memberships beside the one being edited. The list is the navigation
   and the editor is the page; two panes rather than a modal, because setting a
   limit is comparing it to the plan above and below it. */
.fey-plans {
    display: grid;
    grid-template-columns: 232px minmax(0, 1fr);
    gap: var(--s5);
    align-items: start;
}

.fey-plans-list {
    display: flex;
    flex-direction: column;
    gap: var(--s2);
    position: sticky;
    top: var(--s5);
}

.fey-plan-tab {
    display: flex;
    flex-direction: column;
    gap: 3px;
    width: 100%;
    text-align: left;
    padding: var(--s3) var(--s4);
    border-radius: var(--fey-radius);
    border: 1px solid var(--fey-line);
    background: var(--fey-surface);
    cursor: pointer;
    transition: border-color .16s ease, background .16s ease;
}

.fey-plan-tab:hover { border-color: var(--fey-line-strong); }
.fey-plan-tab.on { border-color: var(--fey-primary); background: var(--fey-primary-soft); }

.fey-plan-tab-name { font-size: 14px; font-weight: 550; color: var(--fey-ink); }
.fey-plan-tab-price { font-size: 12.5px; color: var(--fey-ink-soft); }

.fey-plan-tab-note {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    font-size: 11.5px;
    margin-top: 2px;
}

.fey-plans-editor { display: flex; flex-direction: column; gap: var(--s4); min-width: 0; }

/* One limit: what it is on the left, what this package says on the right. The
   explanation sits under the name rather than in a tooltip — an operator setting
   a number nobody explained sets it wrong once and never trusts the screen again. */
.fey-limits { display: flex; flex-direction: column; }

.fey-limit {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 168px;
    gap: var(--s4);
    align-items: start;
    padding: var(--s3) 0;
    border-top: 1px solid var(--fey-line);
}

.fey-limit:first-child { border-top: 0; padding-top: 0; }

.fey-limit-say { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.fey-limit-label { font-size: 13.5px; font-weight: 500; color: var(--fey-ink); }

.fey-limit-hint {
    font-size: 12px;
    line-height: 1.5;
    color: var(--fey-ink-faint);
}

.fey-limit-input { display: flex; flex-direction: column; gap: 4px; }

.fey-limit-foot {
    font-size: 11px;
    color: var(--fey-ink-faint);
}

@media (max-width: 860px) {
    .fey-plans { grid-template-columns: 1fr; }
    .fey-plans-list { position: static; flex-direction: row; flex-wrap: wrap; }
    .fey-plan-tab { width: auto; flex: 1 1 180px; }
    .fey-limit { grid-template-columns: 1fr; gap: var(--s2); }
}

/* ── What your package includes ──
   The customer's half of the same numbers. Deliberately quiet: it is context for
   the machines below it, not a bill. */
.fey-allowance {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: var(--s4) var(--s6);

    /* Capped, so on a wide screen the figure stays beside its label instead of
       drifting to the far side of the card and reading as somebody else's number. */
    max-width: 940px;
}

.fey-allowance-line { display: flex; flex-direction: column; gap: 6px; }

.fey-allowance-label { font-size: 13px; font-weight: 500; }
.fey-allowance-figure { font-size: 13px; color: var(--fey-ink-soft); font-variant-numeric: tabular-nums; }

.fey-allowance-note {
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--fey-ink-faint);
}

.fey-allowance-plan { display: flex; align-items: baseline; gap: 6px; font-size: 13px; }
.fey-allowance-plan-name { font-weight: 550; }

.fey-allowance-blurb {
    margin: 0 0 var(--s4);
    font-size: 13px;
    color: var(--fey-ink-soft);
}

.fey-allowance-foot {
    margin: var(--s4) 0 0;
    padding-top: var(--s3);
    border-top: 1px solid var(--fey-line);
    font-size: 11.5px;
    color: var(--fey-ink-faint);
}

/* ── The rest of the package ──
   Name and value on one line, one line per limit. A table would promise you can
   compare across packages; this is the one you are on, so it reads as a list. */
.fey-includes-group + .fey-includes-group { margin-top: var(--s5); }

.fey-includes {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    gap: 0 var(--s6);
    margin-top: var(--s2);

    /* Capped for the same reason the allowance is: on a wide card the value drifts
       so far from its name that the eye pairs it with the wrong one. */
    max-width: 1040px;
}

.fey-include {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--s3);
    padding: 7px 0;
    border-bottom: 1px solid var(--fey-line);
    font-size: 13px;
}

.fey-include-label { color: var(--fey-ink); }

.fey-include-value {
    color: var(--fey-ink-soft);
    font-variant-numeric: tabular-nums;
}

/* What the package does not give, said quietly rather than in red: a thing you did
   not buy is not a problem with your account. */
.fey-include-value.off { color: var(--fey-ink-faint); }

/* ── Your space on a machine that is not yours ──
   The figure leads and the facts follow it, because the only number somebody came
   for is how much room is left. No memory, no load: those belong to the machine,
   and the machine is not what this block is about. */
.fey-shared {
    display: grid;
    grid-template-columns: minmax(220px, 300px) minmax(0, 1fr);
    gap: var(--s5);
    align-items: start;
}

.fey-shared-figure { display: flex; flex-direction: column; gap: 4px; }

.fey-shared-facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: var(--s4);
}

@media (max-width: 720px) {
    .fey-shared { grid-template-columns: 1fr; }
}

/* ── Where the name actually goes ──
   Under the field where it is typed, because the two are one question. Quiet
   when it is right; a name pointing somewhere else is the only loud state. */
.fey-dns {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-top: -6px;
    padding: var(--s3);
    border-radius: 10px;
    border: 1px solid var(--fey-line);
    background: var(--fey-paper);
    font-size: 12.5px;
}

.fey-dns-points.ok { color: #4A9E74; }
.fey-dns-points.wrong { color: #C0553F; font-weight: 500; }

.fey-dns-say { color: var(--fey-ink-soft); line-height: 1.5; }

/* ── The address a stage answers on ──
   Under the state line, quiet: it is a fact about the stage, not a call to act.
   The link to change it reads as text, because naming a domain is a decision
   somebody makes once and a button would keep asking. */
.fey-road-domain {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 4px;
    font-size: 12px;
}

.fey-linkish {
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    color: var(--fey-primary);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 2px;
}

.fey-linkish:hover { color: var(--fey-ink); }

/* ── How long a stage has left ──
   The bar carries the feeling and the words carry the fact. Narrow, because a
   countdown that dominates the row would make sleeping feel like a problem —
   it is the thing that makes a cheap plan affordable. */
.fey-road-idle {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    margin-top: 5px;
    font-size: 11.5px;
}

.fey-road-idle .fey-meter { width: 88px; flex: 0 0 auto; }

/* ── Keeping a stage awake ──
   A small pill rather than a link, because it is something you can buy and the
   thing you can buy should look like an object. Three states, and only one of
   them is loud: the one you do not have yet. */
.fey-pin {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 999px;
    border: 1px solid var(--fey-line-strong);
    background: var(--fey-surface);
    color: var(--fey-ink-soft);
    font-size: 11px;
    font-weight: 500;
    line-height: 1.6;
    cursor: pointer;
    text-decoration: none;
    transition: border-color .16s ease, background .16s ease, color .16s ease;
}

.fey-pin:hover { border-color: var(--fey-primary); color: var(--fey-ink); }
.fey-pin:disabled { opacity: .5; cursor: default; }
.fey-pin svg { width: 11px; height: 11px; }

/* On: quiet and settled. It is already doing what you asked, so it has nothing
   to sell you — the dot is the only thing that says it is live. */
.fey-pin.on {
    border-color: rgba(74, 158, 116, 0.35);
    background: rgba(74, 158, 116, 0.07);
    color: #3B7D5C;
}

.fey-pin-dot {
    width: 5px; height: 5px;
    border-radius: 50%;
    background: #4A9E74;
}

/* Locked: the one you do not have. Tinted rather than greyed out — a disabled
   look says "broken", and this is not broken, it is for sale. */
.fey-pin.locked {
    border-color: var(--fey-primary);
    background: var(--fey-primary-soft);
    color: var(--fey-primary);
}

.fey-pin.locked:hover {
    background: var(--fey-primary);
    color: #fff;
}

/* ── Fey's worker on a code machine ──
   Set apart from the machine's own numbers: it is Fey's software on somebody's
   droplet, and confusing the two is how an operator restarts the wrong thing. */
.fey-worker {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: var(--s3) var(--s4);
    border-radius: 10px;
    border: 1px solid var(--fey-line);
    background: var(--fey-paper);
}

.fey-worker-name { font-size: 13px; font-weight: 550; }
.fey-worker-state { font-size: 12px; color: var(--fey-ink-soft); }
.fey-worker-state.ok { color: #3B7D5C; }
.fey-worker-state.wrong { color: #C0553F; font-weight: 500; }

.fey-worker-say { font-size: 12px; line-height: 1.5; color: var(--fey-ink-soft); }

/* ── A step the agent took ──
   Small and grey on purpose. It is what the work looked like, not what it
   concluded, and giving it the weight of a sentence turns a conversation into a
   terminal that happens to speak Spanish. */
.fey-msg-doing {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 8px;
    font-size: 12px;
    color: var(--fey-ink-faint);
    padding: 1px 0;
}

.fey-msg-tool { font-weight: 500; color: var(--fey-ink-soft); }

/* The agent's own lines, told apart from Fey narrating its own machinery. */
.fey-msg-agent .fey-msg-who { color: var(--fey-primary); }

/* ── The agent's keys ──
   A list rather than cards: a key is a line of text and a decision about which
   one is in use, and giving each one a card would make three keys look like
   three servers. */
.fey-keys { display: flex; flex-direction: column; }

.fey-key {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: var(--s3);
    padding: var(--s3) 0;
    border-top: 1px solid var(--fey-line);
}

.fey-key:first-child { border-top: 0; padding-top: 0; }

/* ── Which half of the project the frame shows ──
   Two segments rather than a dropdown: there are two of them and both fit, so a
   menu would be a click to see what a glance could have told you. */
.fey-halves {
    display: inline-flex;
    border-radius: 8px;
    border: 1px solid var(--fey-line-strong);
    overflow: hidden;
}

.fey-halves button {
    border: 0;
    background: var(--fey-surface);
    color: var(--fey-ink-soft);
    font: inherit;
    font-size: 11.5px;
    padding: 4px 11px;
    cursor: pointer;
    transition: background .15s ease, color .15s ease;
}

.fey-halves button + button { border-left: 1px solid var(--fey-line-strong); }
.fey-halves button:hover { color: var(--fey-ink); }
.fey-halves button.on { background: var(--fey-primary); color: #fff; }

/* ── Draft is ahead of the next stage ──
   Floating over the preview rather than stacked above it: a notice that resizes
   the page moves what somebody was reading, and this one appears while they are
   looking. Centred at the top because that is where a browser puts its own
   notices, and people already know to look there. */
.fey-preview-pill {
    position: absolute;
    top: var(--s4);
    left: 50%;
    transform: translateX(-50%);
    z-index: 5;

    display: flex;
    align-items: center;
    gap: 10px;
    max-width: calc(100% - var(--s6));

    padding: 7px 8px 7px 16px;
    border-radius: 999px;
    border: 1px solid var(--fey-line-strong);
    background: rgba(255, 255, 255, 0.92);
    backdrop-filter: blur(8px);
    box-shadow: 0 6px 22px rgba(45, 42, 62, 0.14);

    font-size: 12.5px;
    color: var(--fey-ink);
    animation: pill-in .28s ease both;
}

.fey-preview-pill span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.fey-preview-pill button {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    border: 0;
    border-radius: 999px;
    padding: 5px 13px;
    background: var(--fey-primary);
    color: #fff;
    font: inherit;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
}

.fey-preview-pill button:disabled { opacity: .6; cursor: default; }

/* Nothing to press, so nothing to leave room for. */
.fey-preview-pill-working { padding-right: 16px; color: var(--fey-ink-soft); }

/* ── The preview while it is being replaced ── */

.fey-preview-bar {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 2px;
    z-index: 6;
    overflow: hidden;
    background: var(--fey-primary-tint);
}
.fey-preview-bar::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 38%;
    background: var(--fey-primary);
    animation: preview-sweep 1.2s ease-in-out infinite;
}
@keyframes preview-sweep {
    from { transform: translateX(-100%); }
    to   { transform: translateX(320%); }
}

/* Quiet, not hidden. Somebody may still be reading the page that is up. */
.fey-preview-frame { transition: opacity .35s ease; }
.fey-work-preview.is-publishing .fey-preview-frame { opacity: .68; }

/* ── What the API offers ── */

.fey-preview-docs {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    padding: var(--s5) var(--s6) var(--s8);
}

.fey-endpoints-head {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--s4);
    padding-bottom: var(--s4);
    margin-bottom: var(--s2);
    border-bottom: 1px solid var(--fey-line);
}
.fey-endpoints-title { font-size: 15px; font-weight: 550; color: var(--fey-ink); }
.fey-endpoints-raw { font-size: 12px; color: var(--fey-ink-soft); text-decoration: none; }
.fey-endpoints-raw:hover { color: var(--fey-primary); text-decoration: underline; }

.fey-endpoints-group {
    margin: var(--s5) 0 var(--s2);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--fey-ink-faint);
}

.fey-endpoint { border-bottom: 1px solid var(--fey-line-soft); }
.fey-endpoint:last-child { border-bottom: 0; }
.fey-endpoint.is-open { background: var(--fey-surface-sunken); border-radius: 8px; }

/* The whole row opens it, so the whole row is the button — and it has to stop looking like
   one, because forty buttons stacked is a wall rather than a list. */
.fey-endpoint-head {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    width: 100%;
    padding: 9px 10px;
    border: 0;
    background: none;
    font: inherit;
    text-align: left;
    cursor: pointer;
    border-radius: 8px;
}
.fey-endpoint-head:hover { background: var(--fey-surface-sunken); }
.fey-endpoint.is-open .fey-endpoint-head:hover { background: none; }

.fey-endpoint-body { min-width: 0; flex: 1; display: block; }
.fey-endpoint-path { font-size: 12.5px; color: var(--fey-ink); word-break: break-all; }
.fey-endpoint-said { margin-top: 2px; font-size: 12px; color: var(--fey-ink-soft); }

/* The verb, in a fixed lane so the paths line up under each other. A list of endpoints is read
   down the path column, and a ragged left edge makes that impossible. */
.fey-verb {
    flex: 0 0 58px;
    text-align: center;
    padding: 3px 0;
    border-radius: 5px;
    font-size: 10.5px;
    font-weight: 650;
    letter-spacing: .04em;
    color: #fff;
    background: var(--fey-ink-faint);
}
.fey-verb-get { background: #3a7bd5; }
.fey-verb-post { background: #3f9a6a; }
.fey-verb-put { background: #c58a2e; }
.fey-verb-patch { background: #a97cc4; }
.fey-verb-delete { background: #c25b5b; }

.fey-endpoint-bits { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 6px; }
.fey-bit {
    padding: 1px 7px;
    border-radius: 999px;
    border: 1px solid var(--fey-line);
    font-size: 10.5px;
    color: var(--fey-ink-soft);
    background: var(--fey-surface);
}
.fey-bit-body { border-style: dashed; }
.fey-bit-ok { color: #3f9a6a; border-color: #cbe4d6; }
.fey-bit-bad { color: #c25b5b; border-color: #eed3d3; }

/* ── Trying one ── */

.fey-endpoints-auth { margin: var(--s3) 0 var(--s2); }
.fey-endpoints-auth .fey-input { width: 100%; font-size: 12px; }

.fey-try { padding: 2px 12px 14px 12px; }
.fey-try-field { display: block; margin-bottom: 8px; font-size: 11.5px; }
.fey-try-field .fey-input { width: 100%; margin-top: 3px; font-size: 12px; }
.fey-try-in { opacity: .65; }
.fey-try-body { resize: vertical; line-height: 1.5; }

.fey-try-go {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--s4);
    margin-top: 10px;
}
.fey-try-url { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.fey-try-answer { margin-top: 12px; }
.fey-try-status { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; font-size: 11.5px; }
.fey-try-out {
    margin: 8px 0 0;
    padding: 10px 12px;
    max-height: 340px;
    overflow: auto;
    border-radius: 8px;
    border: 1px solid var(--fey-line);
    background: var(--fey-surface);
    font-size: 11.5px;
    line-height: 1.55;
    white-space: pre-wrap;
    word-break: break-word;
}

/* ── Two steps and a command, for connecting a plan ── */

.fey-steps-plain { display: grid; gap: 8px; margin-bottom: var(--s3); font-size: 12.5px; color: var(--fey-ink-soft); }
.fey-step-n {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 18px;
    height: 18px;
    margin-right: 7px;
    border-radius: 50%;
    background: var(--fey-primary-tint);
    color: var(--fey-primary);
    font-size: 10.5px;
    font-weight: 650;
}
.fey-command {
    margin: 0 0 var(--s4);
    padding: 10px 12px;
    border-radius: 8px;
    border: 1px solid var(--fey-line);
    background: var(--fey-surface-sunken);
    font-size: 12.5px;
    user-select: all;
}

/* ── The change a step made, in red and green ── */

.fey-patch {
    margin: 4px 0 6px 0;
    padding: 8px 10px;
    border-radius: 8px;
    border: 1px solid var(--fey-line);
    background: var(--fey-surface-sunken);
    font-size: 11.5px;
    line-height: 1.55;
    max-height: 320px;
    overflow: auto;
}
/* Whole lines, never wrapped: a wrapped line in a diff reads as two changes. */
.fey-patch > div { white-space: pre; }
.fey-patch-out { color: #b04747; background: rgba(194, 91, 91, 0.07); }
.fey-patch-in { color: #2f7d55; background: rgba(63, 154, 106, 0.09); }
.fey-patch-more { margin-top: 4px; color: var(--fey-ink-faint); font-style: italic; }

/* ── The connection to Fey ──
   Hidden until the framework says otherwise: it adds one of its own classes to this element and
   expects the page to have decided what each of them looks like. */

.fey-reconnect { display: none; }
.fey-reconnect.components-reconnect-show,
.fey-reconnect.components-reconnect-failed,
.fey-reconnect.components-reconnect-rejected {
    display: flex;
    position: fixed;
    inset: 0;
    z-index: 3000;
    align-items: flex-start;
    justify-content: center;
    padding-top: 18vh;
    background: rgba(45, 42, 62, 0.28);
    backdrop-filter: blur(3px);
}

.fey-reconnect-card {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 14px 18px;
    border-radius: 999px;
    border: 1px solid var(--fey-line-strong);
    background: var(--fey-surface);
    box-shadow: 0 10px 34px rgba(45, 42, 62, 0.18);
    font-size: 13px;
    color: var(--fey-ink);
}

/* One card, three sentences, and the framework decides which. Each state shows its own line and
   the one button that does anything about it. */
.fey-reconnect-trying, .fey-reconnect-failed, .fey-reconnect-rejected,
.fey-reconnect-retry, .fey-reconnect-reload { display: none; }
.fey-reconnect-card .fey-spin { display: none; }

.components-reconnect-show .fey-reconnect-trying,
.components-reconnect-show .fey-spin { display: inline-flex; }

.components-reconnect-failed .fey-reconnect-failed,
.components-reconnect-failed .fey-reconnect-retry { display: inline-flex; }

.components-reconnect-rejected .fey-reconnect-rejected,
.components-reconnect-rejected .fey-reconnect-reload { display: inline-flex; }

.fey-reconnect-card button {
    border: 0;
    border-radius: 999px;
    padding: 5px 14px;
    background: var(--fey-primary);
    color: #fff;
    font: inherit;
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
}

.fey-endpoints-none { padding-top: var(--s6); }
.fey-endpoints-tried { margin-top: var(--s4); text-align: center; font-size: 11.5px; line-height: 1.7; }

@keyframes pill-in {
    from { opacity: 0; transform: translate(-50%, -8px); }
    to   { opacity: 1; transform: translate(-50%, 0); }
}

/* The preview pane becomes the pill's frame of reference. */
.fey-work-preview { position: relative; }
