/* ============================================================================
   *nix Install Guides — Tokyo Night
   ----------------------------------------------------------------------------
   Consolidated. The previous revision had .app-category-header defined four
   times with conflicting values, and five selectors left dangling by a
   partially-applied edit (a selector with no `{`, which silently swallows the
   next rule). One of those casualties was the .my-tools-box box itself, which
   is why the tilas01 suite had no border or background while the neighbouring
   "Other Security Tools" box did.
   ========================================================================= */

:root {
    --bg-color: #1a1b26;
    --bg-dark: #13141c;
    --bg-darker: #16161e;
    --bg-lighter: #24283b;
    --fg-color: #a9b1d6;
    --fg-dim: #7f88ad;
    --heading-color: #c0caf5;
    --accent-blue: #7aa2f7;
    --accent-purple: #bb9af7;
    --accent-cyan: #7dcfff;
    --accent-green: #9ece6a;
    --accent-red: #f7768e;
    --accent-orange: #ff9e64;
    --accent-yellow: #e0af68;

    /* These two were referenced ~30 times across every page but never
       defined, so those borders and that text rendered as `unset`. */
    --border-color: #2f3450;
    --text-color: #c0caf5;

    /* Flat translucent tints of the accents, used for panel backgrounds.
       Deliberately single colours: this design uses no gradients. */
    --tint-cyan:   rgba(125, 207, 255, 0.06);
    --tint-orange: rgba(255, 158, 100, 0.06);
    --tint-purple: rgba(187, 154, 247, 0.06);
    --tint-green:  rgba(158, 206, 106, 0.06);
    --tint-red:    rgba(247, 118, 142, 0.08);
    --tint-blue:   rgba(122, 162, 247, 0.06);

    --font-mono: "JetBrains Mono", "Fira Code", Consolas, monospace,
                 "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";

    /* Minimum comfortable hit target for touch. */
    --tap-target: 44px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* `hidden` has to actually hide.
   The browser's own `[hidden] { display: none }` is a user-agent rule, so any
   author rule setting `display` on the same element beats it — and several here
   do. `.iso-badge` is inline-flex and `.arch-tabs` is flex, so both stayed on
   screen with the attribute set, and the ISO page showed its Arch verification
   tabs and its "not verified yet" badge underneath a panel explaining that this
   page cannot verify that image at all. `!important` is warranted: an element
   carrying `hidden` is being hidden, and nothing should be able to argue. */
[hidden] { display: none !important; }

body {
    background-color: var(--bg-color);
    color: var(--fg-color);
    font-family: var(--font-mono);
    line-height: 1.6;
    padding: clamp(0.8rem, 3vw, 2rem);
    max-width: 1800px;
    margin: 0 auto;
    font-size: clamp(0.82rem, 1.4vw, 1rem);
    -webkit-text-size-adjust: 100%;   /* stop iOS inflating text in landscape */
    text-size-adjust: 100%;
}

a { color: var(--accent-blue); text-decoration: none; transition: color 0.2s; }
a:hover { color: var(--accent-cyan); text-decoration: underline; }

/* Visible keyboard focus everywhere, since several controls are custom-drawn. */
:focus-visible {
    outline: 2px solid var(--accent-cyan);
    outline-offset: 2px;
}

h1, h2, h3 { color: var(--heading-color); margin-bottom: 0.8rem; }

header { text-align: center; margin-bottom: 2rem; position: relative; }

.banner {
    width: 100%;
    /* Sized to sit above the page rather than lead it, but the wordmark still
       has to be readable — at clamp(200px, 24vw, 320px) it was not. The lower
       bound is set by the longest label in the set rendering legibly:
       RASPBERRY PI GUIDES, not the short ones. */
    max-width: clamp(260px, 30vw, 400px);
    margin: 0 auto 0.4rem;
    display: block;
    transition: transform 0.2s, filter 0.2s;
    background: transparent;
    image-rendering: auto;
}
.banner:hover { transform: scale(1.015); filter: brightness(1.07); }
.banner-link { display: block; text-align: center; text-decoration: none; }

/* The attribution, as text rather than pixels.
   It used to be drawn inside the banner image at 7px tall, which survives a
   full-width README and does not survive being scaled to `.banner`'s
   max-width — it became a green smudge. Real text scales with the viewport
   instead of against it, and stays selectable and linkable. Green, matching
   the version still baked into the README copy, so the two read as one thing
   in two places. */
.banner-credit {
    text-align: center;
    margin: -0.2rem 0 0.8rem;
    font-family: var(--font-mono);
    font-size: clamp(0.72rem, 1.4vw, 0.95rem);
    letter-spacing: 0.06em;
}
.banner-credit a { color: var(--accent-green); text-decoration: none; }
.banner-credit a:hover { text-decoration: underline; }

/* ─── Header controls: emoji-only, absolute top-right ─────────────────────── */
/* Control cluster.
   Top right, and inset rather than flush to the edge: a control in the very
   corner is the one a phone's rounded display clips and a browser's back
   gesture swallows. Order is the tooltip switch, the source repository, then
   this session's history — the switch first because it is the control that
   explains all the others. */
#header-controls {
    position: absolute;
    top: 12px;
    right: 16px;
    display: flex;
    align-items: center;
    gap: 10px;
    z-index: 100;
}
#header-controls button {
    background: transparent;
    border: none;
    font-size: 1.5rem;
    cursor: pointer;
    padding: 4px 6px;
    border-radius: 8px;
    transition: transform 0.15s, filter 0.15s;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: inherit;
    filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.5));
}
#header-controls button:hover { transform: scale(1.15); filter: drop-shadow(0 0 8px var(--accent-cyan)); }
#history-btn { color: var(--accent-purple); }
#history-btn:hover { color: var(--accent-cyan); }
/* Info button: white normally, red when tooltips are disabled. */
#toggle-tooltips-btn { color: #ffffff; }
#toggle-tooltips-btn.disabled { color: var(--accent-red); }


/* Byline under the banner. Green, small, and in the empty space below the
   logo rather than beside it, so the mark itself is untouched. */

/* Anchors in the cluster need the same box as its buttons. */
#header-controls .ctrl-icon {
    background: transparent;
    border: none;
    font-size: 1.5rem;
    line-height: 1;
    cursor: pointer;
    padding: 4px 6px;
    border-radius: 8px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: inherit;
    text-decoration: none;
    filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.5));
    transition: transform 0.15s, filter 0.15s;
    /* Comfortable to hit with a thumb without making the row huge. */
    min-width: 34px;
    min-height: 34px;
}
#header-controls .ctrl-icon:hover,
#header-controls .ctrl-icon:focus-visible {
    transform: scale(1.15);
    filter: drop-shadow(0 0 8px var(--accent-cyan));
    text-decoration: none;
}
#header-controls .ctrl-current { opacity: 0.55; cursor: default; }
#header-controls .ctrl-current:hover { transform: none; }

/* Drawn icons in the control cluster. Pixel art, so let it stay crisp rather
   than be smoothed into mush by the browser's default scaler. */
.ctrl-pixel { display: block; image-rendering: pixelated; }

/* A question's supplementary note — most often the reason an option somebody
   might expect is not on the list. Distinct from .q-help so it reads as an
   aside rather than as part of the question. */
.q-note {
    margin-top: 0.5rem;
    padding-left: 0.7rem;
    border-left: 2px solid var(--accent-orange);
    color: var(--fg-dim);
    font-size: 0.82rem;
    line-height: 1.55;
}

/* ─── The target-system switcher, top left ────────────────────────────────── */
/* Mirrors #header-controls on the opposite side, and inset by the same amount
   so the two clusters sit on one line. It is not styled as another icon button:
   it carries a name as well as a mark, because "which system am I looking at"
   is a question the page should answer without being clicked. */
#os-switch {
    position: absolute;
    top: 12px;
    left: 16px;
    z-index: 100;
    text-align: left;
}

.os-switch-btn {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 0.3rem 0.55rem;
    min-height: 34px;
    color: var(--fg-color);
    font-family: var(--font-mono);
    font-size: 0.82rem;
    cursor: pointer;
    transition: border-color 0.15s, color 0.15s;
}
.os-switch-btn:hover,
.os-switch-btn:focus-visible { border-color: var(--accent-cyan); color: var(--accent-cyan); }
.os-switch-label { white-space: nowrap; }
.os-switch-caret { color: var(--fg-dim); font-size: 0.7rem; }

/* The accent follows the selected system, so the corner is a colour cue as well
   as a label — and stays purple, the family colour, while nothing is chosen. */
#os-switch.os-accent-cyan   .os-switch-btn { border-color: var(--accent-cyan); }
#os-switch.os-accent-purple .os-switch-btn { border-color: var(--accent-purple); }
#os-switch.os-accent-red    .os-switch-btn { border-color: var(--accent-red); }
#os-switch.os-accent-green  .os-switch-btn { border-color: var(--accent-green); }

/* An unfinished system is marked in the header the whole time it is selected,
   not only where it was picked. Someone who chose Gentoo three pages ago and
   has forgotten needs to be reminded before they run the script, not after. */
#os-switch.os-wip .os-switch-btn {
    border-color: var(--accent-orange);
    color: var(--accent-orange);
}
/* On the button, not on the label: the label is hidden on a narrow screen and
   the warning is the last thing that may go with it. */
#os-switch.os-wip .os-switch-btn::after {
    content: "🚧";
    font-size: 0.8rem;
}

.os-switch-menu {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    min-width: 290px;
    max-width: min(360px, 92vw);
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 0.35rem;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    box-shadow: 0 14px 34px rgba(0, 0, 0, 0.6);
}

.os-opt {
    display: flex;
    align-items: flex-start;
    gap: 0.55rem;
    width: 100%;
    text-align: left;
    background: transparent;
    border: 1px solid transparent;
    border-radius: 8px;
    padding: 0.5rem 0.6rem;
    color: var(--fg-color);
    font-family: var(--font-mono);
    cursor: pointer;
    min-height: var(--tap-target);
}
.os-opt:hover, .os-opt:focus-visible { background: var(--bg-lighter); }
.os-opt img { flex: 0 0 auto; margin-top: 0.1rem; }
.os-opt-text { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.os-opt-name { font-size: 0.86rem; font-weight: bold; }
/* Wraps rather than truncates. Several option cards elsewhere on the site were
   sized for short strings and clipped the ones that outgrew them; the text that
   says a guide cannot be installed from is the last text to hide. */
.os-opt-summary {
    font-size: 0.74rem;
    color: var(--fg-dim);
    line-height: 1.45;
    white-space: normal;
}
.os-opt-wip { font-size: 0.68rem; color: var(--accent-orange); font-weight: normal; }

.os-opt.os-accent-cyan   .os-opt-name { color: var(--accent-cyan); }
.os-opt.os-accent-purple .os-opt-name { color: var(--accent-purple); }
.os-opt.os-accent-red    .os-opt-name { color: var(--accent-red); }
.os-opt.os-accent-green  .os-opt-name { color: var(--accent-green); }
.os-opt.is-current { border-color: currentColor; background: var(--bg-lighter); }

/* The verified badge on the ISO page: the Arch mark with a tick beside it.
   The tick is a status readout — lit only after a hash has matched two
   independent mirrors in this session — so it is deliberately not a control
   you can tick yourself. */
.iso-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    background: var(--bg-dark);
    border: 2px solid var(--border-color);
    border-radius: 10px;
    padding: 0.55rem 0.9rem;
    margin: 0 auto 1.2rem;
    transition: border-color 0.25s, background-color 0.25s;
}
.iso-badge img { image-rendering: pixelated; flex: 0 0 auto; }
.iso-badge-tick {
    font-size: 1.15rem;
    line-height: 1;
    font-weight: bold;
    color: var(--fg-dim);
    border: 2px solid var(--border-color);
    border-radius: 5px;
    padding: 0.1rem 0.3rem;
    transition: color 0.25s, border-color 0.25s, background-color 0.25s;
}
.iso-badge-label { font-size: 0.82rem; color: var(--fg-dim); }
.iso-badge.is-verified { border-color: var(--accent-green); background: var(--tint-green); }
.iso-badge.is-verified .iso-badge-tick {
    color: var(--accent-green);
    border-color: var(--accent-green);
    background: var(--bg-dark);
}
.iso-badge.is-verified .iso-badge-label { color: var(--accent-green); }

/* An unexported history is one tab-close away from being gone. */
#history-btn.ctrl-unsaved::after {
    content: "";
    position: absolute;
    top: 2px;
    right: 2px;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--accent-orange);
}
#history-btn { position: relative; }

/* Present to screen readers, absent from the layout. */
.visually-hidden {
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0; border: 0;
    clip: rect(0 0 0 0);
    clip-path: inset(50%);
    overflow: hidden;
    white-space: nowrap;
}

/* ─── Nav ─────────────────────────────────────────────────────────────────── */
.main-nav {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-top: 0.5rem;
}
.nav-sep {
    color: var(--bg-lighter);
    font-size: 1.1rem;
    -webkit-user-select: none;
    user-select: none;
}
.nav-link { font-size: 1.1rem; font-weight: bold; margin: 0 10px; }

/* Touch targets.
   On a touch screen the nav links measured 28px tall and the header control
   icons 29px — below the 44px this project already defines as --tap-target, and
   below the WCAG 2.5.8 / platform minimum. Anything smaller is a link people
   miss and hit the neighbour instead.

   Keyed on EITHER a coarse pointer OR a narrow viewport. pointer:coarse alone
   is not enough: some devices and embedded webviews report a fine pointer at
   phone width, and they need the larger targets just as much. Desktop mice at
   full width keep the tighter, denser layout they can hit precisely. */
@media (pointer: coarse), (max-width: 768px) {
    .main-nav .nav-link,
    .nav-bar .nav-link {
        display: inline-flex;
        align-items: center;
        min-height: var(--tap-target);
        padding: 0 0.35rem;
    }
    #header-controls .ctrl-icon,
    #header-controls button {
        min-width: var(--tap-target);
        min-height: var(--tap-target);
    }
}

section {
    background-color: var(--bg-darker);
    padding: 2rem;
    border-radius: 12px;
    margin-bottom: 2rem;
    border: 1px solid var(--bg-lighter);
}

/* ─── Form ────────────────────────────────────────────────────────────────── */
.form-group { margin-bottom: 1rem; }

label {
    display: block;
    margin-bottom: 0.3rem;
    color: var(--accent-cyan);
    font-size: 0.92rem;
}

/* Same appearance as a <label>, but for a group heading that does not point at
   a single labelable control. */
.group-label {
    display: block;
    color: var(--accent-cyan);
    font-size: 0.92rem;
}

/* Proprietary app blocked by the libre policy: visibly inert, not just dimmed. */
.app-card.app-disabled {
    opacity: 0.45;
    cursor: not-allowed;
    border-style: dashed;
}
.app-card.app-disabled a { pointer-events: none; }

/* A label with an action button on the same row (e.g. "Enable All"). */
.group-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.4rem;
}
.group-header label { margin-bottom: 0; }

input, select {
    width: 100%;
    padding: 0.6rem;
    background-color: var(--bg-color);
    color: var(--fg-color);
    border: 1px solid var(--accent-purple);
    border-radius: 6px;
    font-family: var(--font-mono);
    font-size: 0.9rem;
}

/* Selects: normalise the native arrow away so Firefox, Chromium and WebKit
   all render the same control. Without appearance:none each engine draws its
   own dropdown chrome at a different height. */
select {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    /* Chevron as a single-colour inline SVG. No gradients anywhere in this
       stylesheet: the palette is used flat, as designed. */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23bb9af7' stroke-width='1.6' stroke-linecap='round'/%3E%3C/svg%3E");
    background-position: right 0.85rem center;
    background-size: 10px 6px;
    background-repeat: no-repeat;
    padding-right: 2.2rem;
    min-height: var(--tap-target);
}
/* Firefox keeps a focus inner-ring on selects; remove it. */
select:-moz-focusring { color: transparent; text-shadow: 0 0 0 var(--fg-color); }
/* Ensure the dropdown list itself is readable on all platforms. */
select option { background-color: var(--bg-darker); color: var(--fg-color); }

input:focus, select:focus {
    outline: none;
    border-color: var(--accent-blue);
    box-shadow: 0 0 5px var(--accent-blue);
}

/* Greyed placeholder for "No Selection Provided". */
select:invalid, select.placeholder { color: var(--fg-dim); }

/* Validation: outline the offending control rather than listing it in prose. */
.field-invalid {
    border-color: var(--accent-red) !important;
    box-shadow: 0 0 0 1px var(--accent-red);
}
.app-card.card-invalid {
    border-color: var(--accent-orange);
    background: var(--tint-orange);
}
#generate-error-box { text-align: left; }
#generate-error-box ul { margin: 0 0 0 1.1rem; }
#generate-error-box li { margin-bottom: 0.3rem; }

.btn {
    background-color: var(--accent-purple);
    color: var(--bg-color);
    border: none;
    padding: 0.8rem 1.5rem;
    font-size: 1rem;
    font-weight: bold;
    border-radius: 8px;
    cursor: pointer;
    width: 100%;
    font-family: var(--font-mono);
    transition: transform 0.1s, background-color 0.2s;
}
.btn:hover { background-color: var(--accent-blue); transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

/* End-of-form generate block. Deliberately not sticky — it should not follow
   the user around while they are still choosing options. */
.generate-row {
    margin-top: 1.5rem;
    padding: 1.2rem 1rem;
    background: var(--bg-darker);
    border-top: 1px solid var(--accent-cyan);
    border-radius: 8px;
    width: 100%;
}

.btn-container {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    justify-content: center;
    margin-top: 2rem;
}
.btn-container .btn { flex: 1 1 200px; max-width: 300px; }

.alert { padding: 0.8rem; border-radius: 6px; margin-bottom: 0.8rem; font-size: 0.9rem; }
.alert.warning {
    background-color: rgba(247, 118, 142, 0.1);
    border: 1px solid var(--accent-red);
    color: var(--accent-red);
}
.alert.info {
    background-color: rgba(122, 162, 247, 0.1);
    border: 1px solid var(--accent-blue);
    color: var(--accent-blue);
}
.alert.error {
    background-color: rgba(247, 118, 142, 0.12);
    border: 1px solid var(--accent-red);
    color: var(--accent-red);
}

/* ============================================================================
   Cross-browser checkboxes and switches
   ----------------------------------------------------------------------------
   Both are drawn from scratch with appearance:none. `accent-color` alone was
   not enough: Firefox, Chromium, WebKit/Safari and Android WebView each size
   and round native checkboxes differently, so the app grid visibly disagreed
   between browsers.
   ========================================================================= */

input[type="checkbox"] {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    width: 1.05rem;
    height: 1.05rem;
    min-width: 1.05rem;          /* never let flex squash it */
    flex: 0 0 auto;
    margin: 0;
    padding: 0;
    border: 1.5px solid var(--accent-purple);
    border-radius: 4px;
    background-color: var(--bg-color);
    cursor: pointer;
    position: relative;
    display: inline-grid;
    place-content: center;
    transition: background-color 0.15s, border-color 0.15s;
    /* Keep the drawn box crisp rather than letting the UA scale it. */
    vertical-align: middle;
}

/* The tick: a rotated rectangle, so no font or SVG dependency. */
input[type="checkbox"]::before {
    content: "";
    width: 0.3rem;
    height: 0.55rem;
    border: solid var(--bg-color);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg) translate(-1px, -1px) scale(0);
    transition: transform 0.12s ease-out;
}
input[type="checkbox"]:checked {
    background-color: var(--accent-purple);
    border-color: var(--accent-purple);
}
input[type="checkbox"]:checked::before { transform: rotate(45deg) translate(-1px, -1px) scale(1); }
input[type="checkbox"]:disabled { opacity: 0.5; cursor: not-allowed; }
input[type="checkbox"]:focus-visible { outline: 2px solid var(--accent-cyan); outline-offset: 2px; }

/* Larger, green variant used by the libre-policy banner. */
input[type="checkbox"].policy-toggle {
    width: 1.25rem;
    height: 1.25rem;
    min-width: 1.25rem;
    border-color: var(--accent-green);
}
input[type="checkbox"].policy-toggle:checked {
    background-color: var(--accent-green);
    border-color: var(--accent-green);
}

/* ─── Animated switch ─────────────────────────────────────────────────────── */
.switch {
    position: relative;
    display: inline-block;
    width: 40px;
    height: 22px;
    flex: 0 0 auto;
    vertical-align: middle;
}
/* The real input stays in the layout for hit-testing and focus, just invisible. */
.switch input {
    -webkit-appearance: none;
    appearance: none;
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    border: none;
    border-radius: 22px;
    background: transparent;
    opacity: 0;
    cursor: pointer;
    z-index: 2;
}
.switch input::before { content: none; }   /* suppress the checkbox tick */

.slider {
    position: absolute;
    inset: 0;
    background-color: var(--accent-red);   /* off */
    transition: background-color 0.3s;
    border-radius: 22px;
    pointer-events: none;
    border: 1px solid transparent;
}
.slider::before {
    content: "";
    position: absolute;
    height: 16px;
    width: 16px;
    left: 3px;
    bottom: 2px;
    background-color: #ffffff;
    transition: transform 0.3s;
    border-radius: 50%;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}
.switch input:checked + .slider { background-color: var(--accent-blue); }
.switch input:checked + .slider::before { transform: translateX(18px); }
.switch input:focus-visible + .slider { outline: 2px solid var(--accent-cyan); outline-offset: 2px; }
/* `.round` is used in the markup; it carried no rules before. */
.slider.round { border-radius: 22px; }

/* ============================================================================
   Application grids (post-install apps and the two security boxes)
   ========================================================================= */

.app-grid-container {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 0.8rem;
    background: var(--bg-dark);
    padding: 1.2rem;
    border: 1px solid var(--accent-purple);
    border-radius: 8px;
    width: 100%;
}

/* Category headers span the full grid width. Defined once. */
.app-category-header {
    grid-column: 1 / -1;
    color: var(--accent-cyan);
    font-size: 0.78rem;
    font-weight: bold;
    letter-spacing: 0.5px;
    padding: 0.35rem 0.2rem 0.3rem;
    border-bottom: 1px solid rgba(125, 207, 255, 0.18);
    margin-top: 0.5rem;
    margin-bottom: 0.2rem;
}
.app-category-header:first-child { margin-top: 0; }

/* One app per cell: checkbox, icon, name, badges, description. */
.app-card {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem;
    border: 1px solid rgba(255, 255, 255, 0.05);
    border-radius: 6px;
    background: var(--bg-lighter);
    transition: background 0.15s, border-color 0.15s;
    cursor: pointer;
    font-size: 0.88rem;
    width: 100%;
    text-align: left;
    color: var(--fg-color);
    margin: 0;
    min-height: var(--tap-target);
}
.app-card:hover {
    background: rgba(255, 255, 255, 0.08);
    border-color: rgba(255, 255, 255, 0.15);
}
/* Selected state, so the choice reads at a glance. */
.app-card:has(input[type="checkbox"]:checked) {
    border-color: var(--accent-purple);
    background: rgba(187, 154, 247, 0.12);
}

.app-card a {
    font-weight: 600;
    color: var(--fg-color);
    text-decoration: none;
}
.app-card a:hover { color: var(--accent-cyan); text-decoration: underline; }

.app-icon {
    font-size: 1.05rem;
    text-align: center;
    min-width: 1.4rem;
    flex: 0 0 auto;
}

.app-desc {
    color: var(--fg-dim);
    font-size: 0.76rem;
    margin-left: auto;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    flex-shrink: 1;
    min-width: 0;
}

.prop-warn {
    color: var(--accent-red);
    font-weight: bold;
    font-size: 0.85rem;
    cursor: help;
    flex: 0 0 auto;
}

.info-tooltip-icon { opacity: 0.6; cursor: help; flex: 0 0 auto; }
.info-tooltip-icon:hover { opacity: 1; }

/* Gear: reveal on hover, on keyboard focus, and whenever the app is selected.
   It previously had `display:none` both here and inline on every instance,
   with no rule to bring it back, so app configuration was unreachable and any
   app requiring config permanently blocked generation. */
.gear-config-btn {
    display: none;
    cursor: pointer;
    opacity: 0.75;
    transition: opacity 0.2s, transform 0.15s;
    font-size: 0.95rem;
    margin-left: 0.4rem;
    flex: 0 0 auto;
}
.gear-config-btn:hover { opacity: 1; transform: scale(1.15); }
.app-card:hover .gear-config-btn,
.app-card:focus-within .gear-config-btn,
.app-card:has(input[type="checkbox"]:checked) .gear-config-btn { display: inline-block; }

/* An app awaiting configuration is flagged, so the blocking state is visible
   before the user presses Generate. */
.app-card:has(input[data-requires-config="true"][data-configured="false"]:checked) {
    border-color: var(--accent-orange);
    background: rgba(255, 158, 100, 0.12);
}

.btn-configure {
    background: var(--accent-blue);
    border: none;
    color: var(--bg-darker);
    padding: 2px 6px;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.75rem;
    margin-left: 5px;
    font-family: inherit;
}

/* ─── tilas01 suite box (cyan) ────────────────────────────────────────────── */
.my-tools-box {
    border: 1px solid var(--accent-cyan);
    border-radius: 10px;
    background: var(--tint-cyan);
    padding: 0.9rem;
    margin-top: 1.2rem;
}
.my-tools-header,
.other-sec-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}
.my-tools-title {
    color: var(--accent-cyan);
    font-weight: bold;
    font-size: 0.92rem;
    letter-spacing: 0.4px;
}
.my-tools-box .app-grid-container {
    border-color: var(--accent-cyan);
    background: rgba(125, 207, 255, 0.05);
}
.app-card.tilas-tool { border-left: 3px solid var(--accent-cyan); }
.app-card.tilas-tool:has(input:checked) { border-color: var(--accent-cyan); background: rgba(125, 207, 255, 0.14); }

/* ─── Third-party security box (orange) ───────────────────────────────────── */
.other-sec-box {
    border: 1px solid var(--accent-orange);
    border-radius: 10px;
    background: var(--tint-orange);
    padding: 0.9rem;
    margin-top: 1.2rem;
}
.other-sec-title {
    color: var(--accent-orange);
    font-weight: bold;
    font-size: 0.92rem;
    letter-spacing: 0.4px;
}
.other-sec-box .app-grid-container {
    border-color: var(--accent-orange);
    background: rgba(255, 158, 100, 0.05);
}
.app-card.other-sec-tool { border-left: 3px solid var(--accent-orange); }
.app-card.other-sec-tool:has(input:checked) { border-color: var(--accent-orange); background: rgba(255, 158, 100, 0.14); }

/* ─── Group "enable all" buttons ──────────────────────────────────────────── */
.my-tools-enable-btn,
.other-sec-enable-btn,
.post-apps-enable-btn {
    border: none;
    border-radius: 6px;
    color: var(--bg-darker);
    font-weight: bold;
    font-size: 0.78rem;
    padding: 0.35rem 0.75rem;
    cursor: pointer;
    transition: opacity 0.2s, transform 0.15s;
    font-family: inherit;
    white-space: nowrap;
    width: auto;
    min-height: 32px;
}
.my-tools-enable-btn:hover,
.other-sec-enable-btn:hover,
.post-apps-enable-btn:hover { opacity: 0.88; transform: scale(1.03); }
/* Flat palette colours, one per group. */
.my-tools-enable-btn { background: var(--accent-cyan); }
.other-sec-enable-btn { background: var(--accent-orange); }
.post-apps-enable-btn { background: var(--accent-purple); }
/* Selected/locked state: the palette green, still flat. */
.my-tools-enable-btn[aria-pressed="true"],
.other-sec-enable-btn[aria-pressed="true"],
.post-apps-enable-btn[aria-pressed="true"] { background: var(--accent-green); }

#post_apps_container strong { margin-top: 0.3rem; }

/* ─── Layered encryption block ────────────────────────────────────────────── */
/* Numbered layers with a consistent header row, so the four decisions read as
   one stack rather than four unrelated dropdowns. */
.enc-stack {
    background: var(--bg-dark);
    border: 1px solid var(--accent-purple);
    border-radius: 8px;
    padding: 1rem 1.1rem;
    margin-top: 0.5rem;
}
.enc-intro {
    font-size: 0.82rem;
    color: var(--fg-dim);
    margin: 0 0 1rem;
}
.enc-layer + .enc-layer { margin-top: 0.9rem; padding-top: 0.9rem; border-top: 1px solid var(--border-color); }
.enc-layer-head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-bottom: 0.4rem;
}
.enc-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.35rem;
    height: 1.35rem;
    border-radius: 4px;
    color: var(--bg-darker);
    font-size: 0.75rem;
    font-weight: bold;
    flex: 0 0 auto;
}
.enc-layer-title {
    color: var(--heading-color);
    font-weight: bold;
    font-size: 0.9rem;
}
.enc-hint {
    margin-left: auto;
    font-size: 0.72rem;
    color: var(--fg-dim);
    white-space: nowrap;
}
.enc-warn {
    font-size: 0.76rem;
    color: var(--accent-red);
    margin: 0.5rem 0 0;
    padding: 0.5rem 0.7rem;
    background: var(--tint-red);
    border-left: 3px solid var(--accent-red);
    border-radius: 4px;
}
@media screen and (max-width: 480px) {
    .enc-hint { margin-left: 0; flex-basis: 100%; white-space: normal; }
}

/* ─── Generic checkbox grid ───────────────────────────────────────────────── */
.checkbox-grid {
    display: grid;                 /* was missing, so this never gridded */
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
    gap: 12px;
    margin-top: 10px;
}
.checkbox-item { display: flex; align-items: center; gap: 0.4rem; font-size: 0.9rem; }

/* ============================================================================
   Output
   ========================================================================= */

.output-box {
    word-wrap: break-word;
    overflow-wrap: break-word;
    white-space: pre-wrap;
    background: var(--bg-dark);
    padding: 1.2rem 1.5rem;
    border-radius: 16px;
    max-width: 100%;
    box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.5);
    font-family: var(--font-mono);
    font-size: 0.88rem;
    line-height: 1.6;
    overflow-x: auto;
    margin-bottom: 0.5rem;
}
.output-box.editor-md { border: 1px solid var(--accent-cyan); }
.output-box.editor-sh, .output-box.editor-script { border: 1px solid var(--accent-blue); }
.output-box.editor-sc { border: 1px solid var(--accent-purple); }
.output-box.preview-md { border: 1px solid var(--accent-purple); color: var(--fg-color); }
.output-box.oneliner {
    border: 1px solid var(--accent-green);
    background: rgba(158, 206, 106, 0.05);
    font-size: 0.82rem;
}

.output-title {
    font-weight: bold;
    font-size: 1.05rem;
    margin: 1.2rem 0 0.4rem;
    padding-bottom: 0.3rem;
    border-bottom: 2px solid;
}
.output-title.md-edit { color: var(--accent-cyan); border-color: var(--accent-cyan); }
.output-title.md-prev { color: var(--accent-purple); border-color: var(--accent-purple); }
.output-title.sh-edit, .output-title.script-edit { color: var(--accent-blue); border-color: var(--accent-blue); }
.output-title.ssh-cmd { color: var(--accent-green); border-color: var(--accent-green); }
.output-title.sc-edit { color: var(--accent-purple); border-color: var(--accent-purple); }

.output-actions {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin-bottom: 0.3rem;
}

/* ─── Rendered markdown ───────────────────────────────────────────────────── */
.markdown-body {
    background-color: var(--bg-color);
    padding: 1.5rem;
    border-radius: 12px;
    white-space: normal;
    font-size: 0.95rem;
    border: 1px solid var(--accent-blue);
    word-wrap: break-word;
    overflow-wrap: break-word;
    max-width: 100%;
}
.markdown-body pre {
    background-color: var(--bg-darker);
    padding: 1rem;
    border-radius: 8px;
    overflow-x: auto;
    border: 1px solid var(--accent-purple);
    white-space: pre-wrap;
    word-wrap: break-word;
}
.markdown-body code {
    color: var(--accent-green);
    background-color: var(--bg-darker);
    padding: 0.15rem 0.35rem;
    border-radius: 4px;
    font-family: var(--font-mono);
}
.markdown-body pre code { color: var(--heading-color); background-color: transparent; padding: 0; }
.markdown-body h1, .markdown-body h2, .markdown-body h3 { margin-top: 1.2rem; }
.markdown-body p { margin: 0.5rem 0; }
.markdown-body ul, .markdown-body ol { margin: 0.5rem 0 0.5rem 1.5rem; }
.markdown-body table { border-collapse: collapse; width: 100%; margin: 0.8rem 0; }
.markdown-body th, .markdown-body td {
    border: 1px solid var(--bg-lighter);
    padding: 0.4rem 0.7rem;
    text-align: left;
}
.markdown-body th { background: var(--bg-darker); color: var(--accent-cyan); }
.markdown-body blockquote {
    border-left: 3px solid var(--accent-purple);
    padding: 0.5rem 1rem;
    margin: 0.5rem 0;
    background: rgba(187, 154, 247, 0.05);
}

/* Any wide block scrolls inside itself rather than the page. */
.markdown-body table, .markdown-body pre { max-width: 100%; }

/* The .token.* rules that were here styled Prism's output. Prism was never
   loaded — its five call sites in script.js were each guarded with
   `if (window.Prism)` and none ever fired — so these selectors matched nothing
   on any page, and two of them carried off-palette colours. Highlighting is now
   done by highlight.js; its .tk-* colours are at the end of this file. */

ul { list-style-type: square; padding-left: 1.5rem; }
ul li { margin-bottom: 0.3rem; }

noscript .js-only { display: none !important; }

/* ─── Layout ──────────────────────────────────────────────────────────────── */
.layout-container { display: flex; gap: 2rem; align-items: flex-start; }
.generator-form { flex: 1; min-width: 0; }

/* ─── Wiki ────────────────────────────────────────────────────────────────── */
.wiki-content {
    padding: 2rem;
    word-wrap: break-word;
    overflow-wrap: break-word;
}

/* ─── Site footer: credits + legal ────────────────────────────────────────── */
/* Present on every page. The legal notice is static HTML rather than injected,
   so it is still there with JavaScript disabled. */
.site-footer {
    margin-top: 3rem;
    padding-top: 2rem;
    border-top: 1px solid var(--bg-lighter);
    text-align: center;
}

/* ─── Footer ──────────────────────────────────────────────────────────────────
   Three blocks, side by side, filling the width. Everything used to sit inside
   one red .legal-notice box: four paragraphs of waiver with the project's own
   name, author and navigation tacked on the end, so the credits read as part of
   the disclaimer and the waiver dominated the whole footer.

   Each block now carries its own accent, because each answers a different
   question — what happens if this breaks, what may I do with it, and whose work
   is this. Built by shared-ui.js from one definition rather than copied into ten
   HTML files. */
.footer-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1.1rem;
    align-items: start;
    text-align: left;
    margin: 1.5rem 0 0;
}

.footer-block {
    padding: 1rem 1.2rem;
    border-radius: 10px;
    font-size: 0.78rem;
    line-height: 1.65;
    color: var(--fg-dim);
    border: 1px solid var(--border-color);
    background: var(--bg-darker);
    /* The waiver is longer than the other two; without this the grid row
       stretches the short ones into mostly empty boxes. */
    height: 100%;
}
.footer-block h2 {
    font-size: 0.85rem;
    letter-spacing: 0.02em;
    margin: 0 0 0.5rem;
}
.footer-block p { margin: 0.5rem 0; }
.footer-block strong { color: var(--fg-color); }
.footer-block a { color: var(--accent-blue); }
.footer-block a:hover { color: var(--accent-cyan); }

/* Red: what happens if this breaks. */
.footer-waiver { border-color: var(--accent-red); background: var(--tint-red); }
.footer-waiver h2 { color: var(--accent-red); }

/* Green: what you may do with it. */
.footer-licence { border-color: var(--accent-green); background: var(--tint-green); }
.footer-licence h2 { color: var(--accent-green); }

/* Purple: whose work this is. Was buried at the bottom of the red box. */
.footer-project { border-color: var(--accent-purple); background: var(--tint-purple); }
.footer-project h2 { color: var(--accent-purple); }

.footer-fineprint { font-size: 0.74rem; opacity: 0.92; }

/* Every destination, built from the same NAV array as the header so this row
   cannot fall behind it — the hand-written one still said "Manual" and had
   never gained the Live Editor or the Cheatsheets. */
.footer-links {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3rem 0.75rem;
    margin: 0.6rem 0;
    font-size: 0.76rem;
}
.footer-links a { white-space: nowrap; }

.footer-credits {
    border-top: 1px solid var(--border-color);
    padding-top: 0.6rem;
    margin-top: 0.7rem;
    font-size: 0.75rem;
}

@media (pointer: coarse), (max-width: 768px) {
    /* One column on a phone, and links become real tap targets rather than a
       dense row of 12px text. */
    .footer-grid { grid-template-columns: 1fr; }
    .footer-links { gap: 0.2rem 0.9rem; }
    .footer-links a,
    .footer-fineprint a {
        display: inline-flex;
        align-items: center;
        min-height: var(--tap-target, 44px);
    }
}

/* ─── Credits ─────────────────────────────────────────────────────────────── */
.credits-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    justify-content: center;
    margin-top: 1rem;
}
.credit-card {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    background: var(--bg-darker);
    border: 1px solid var(--bg-lighter);
    border-radius: 12px;
    padding: 0.8rem 1.2rem;
    min-width: 260px;
    transition: border-color 0.2s;
}
.credit-card:hover { border-color: var(--accent-blue); }
.credit-card img {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 1px solid var(--accent-purple);
}
.credit-card .credit-info { display: flex; flex-direction: column; }
.credit-card .credit-name { color: var(--heading-color); font-weight: bold; font-size: 0.95rem; }
.credit-card .credit-role { color: var(--fg-color); font-size: 0.8rem; }

/* ─── Dropdown (cheatsheets) ──────────────────────────────────────────────── */
.dropdown { position: relative; display: inline-block; }
.dropdown-content {
    display: none;
    position: absolute;
    background-color: var(--bg-darker);
    min-width: 250px;
    box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 0.5);
    z-index: 10;
    border: 1px solid var(--accent-purple);
    border-radius: 5px;
}
.dropdown-content a {
    color: var(--fg-color);
    padding: 10px 14px;
    text-decoration: none;
    display: block;
    font-size: 0.88rem;
}
.dropdown-content a:hover { background-color: var(--bg-lighter); color: var(--accent-cyan); }
.dropdown:hover .dropdown-content,
.dropdown:focus-within .dropdown-content { display: block; }

/* ─── Animations ──────────────────────────────────────────────────────────── */
.form-step { animation: fadeIn 0.4s ease-out; }
@keyframes fadeIn {
    from { opacity: 0; transform: translateY(10px); }
    to { opacity: 1; transform: translateY(0); }
}

/* Respect users who ask for less motion. */
@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ─── Responsive ──────────────────────────────────────────────────────────── */
@media screen and (min-width: 769px) {
    .layout-container { flex-direction: row; }
}

@media screen and (max-width: 768px) {
    body { padding: 0.8rem; }
    header { margin-bottom: 1.5rem; }
    h1 { font-size: 1.4rem; }
    section { padding: 1rem; }
    .btn { padding: 0.7rem 1rem; font-size: 0.95rem; }
    .markdown-body { padding: 0.8rem; font-size: 0.82rem; overflow-x: auto; }
    .wiki-content { padding: 1rem; }
    .nav-link { display: block; margin: 0.4rem 0; }
    .nav-sep { display: none; }
    .layout-container { flex-direction: column; }
    .output-box { padding: 0.8rem; font-size: 0.8rem; border-radius: 12px; }
    .output-title { font-size: 0.95rem; }
    #header-controls { top: 8px; right: 10px; gap: 6px; }
    #header-controls button { font-size: 1.3rem; }
    #os-switch { top: 8px; left: 10px; }
    .os-switch-btn { font-size: 0.75rem; padding: 0.25rem 0.4rem; }
    /* Single column so app names are never clipped on a phone. */
    .app-grid-container { grid-template-columns: 1fr; padding: 0.8rem; }
}

@media screen and (max-width: 480px) {
    body { padding: 0.4rem; }
    h1 { font-size: 1.3rem; }
    .app-desc { display: none; }   /* the tooltip still carries the detail */
    /* Both header clusters are absolutely positioned on the same line, and at
       this width the system name and four control icons no longer fit beside
       each other. The mark and the caret stay — the switcher is still findable
       and still says which system is selected via its colour and the 🚧 badge
       — and the name returns as soon as there is room for it. */
    .os-switch-label { display: none; }
    .os-switch-menu { min-width: min(300px, 88vw); }
}

/* Coarse pointers (touch): the gear can't rely on :hover, so always show it. */
@media (hover: none) {
    .gear-config-btn { display: inline-block; }
    .app-card { min-height: var(--tap-target); }
}

/* ─── Fallback for engines without :has() ─────────────────────────────────────
   Safari gained :has() in 15.4 and Firefox in 121. On anything older the
   selected-state highlighting above is skipped, so keep the gear reachable
   there by revealing it on hover/focus only (already covered) and make sure
   nothing depends on :has() for functionality — only for emphasis. */
@supports not selector(:has(*)) {
    .gear-config-btn { display: inline-block; opacity: 0.6; }
}

/* ─── Welcome dialog: the two required confirmations ──────────────────────────
   Both ticks are mandatory, so the rows have to read as things you act on, not
   as more paragraphs in a wall of legal text. Whole-row hit area, because a
   14px box is not a tap target — the <label> wraps the input so anywhere in the
   row toggles it. */
.legal-check {
    display: flex;
    align-items: flex-start;
    gap: 0.7rem;
    padding: 0.75rem 0.9rem;
    margin-bottom: 0.6rem;
    min-height: var(--tap-target, 44px);
    background: var(--bg-darker, #16161e);
    border: 1px solid var(--border-color, #2d2d3f);
    border-radius: 8px;
    font-size: 0.82rem;
    line-height: 1.6;
    cursor: pointer;
    transition: border-color 0.18s, background 0.18s;
}

.legal-check:hover { border-color: var(--accent-cyan, #7dcfff); }

.legal-check input[type="checkbox"] {
    /* Sized up from the 13px default: this is the control the whole dialog
       hangs on, and it has to be hittable with a thumb. */
    flex: 0 0 auto;
    width: 20px;
    height: 20px;
    margin: 0.12rem 0 0;
    accent-color: var(--accent-green, #9ece6a);
    cursor: pointer;
}

/* Ticked rows go green so the two states are distinguishable at a glance and
   it is obvious which one is still outstanding. */
.legal-check:has(input:checked) {
    border-color: var(--accent-green, #9ece6a);
    background: rgba(158, 206, 106, 0.07);
}

/* Keyboard focus must be visible on the row, not just the box. */
.legal-check:focus-within {
    outline: 2px solid var(--accent-cyan, #7dcfff);
    outline-offset: 2px;
}

@media (pointer: coarse), (max-width: 768px) {
    .legal-check { padding: 0.85rem; font-size: 0.85rem; }
    .legal-check input[type="checkbox"] { width: 22px; height: 22px; }
}

/* Shown on the *nix Install Generator when the chosen desktop only runs on one
   display server. Matches .q-locked in the *nix Install Walkthrough so a locked
   answer looks the same in both front ends. */
.locked-note {
    background: var(--tint-orange, rgba(255, 158, 100, 0.1));
    border-left: 3px solid var(--accent-orange, #ff9e64);
    border-radius: 0 6px 6px 0;
    padding: 0.55rem 0.75rem;
    margin: 0.5rem 0 0;
    font-size: 0.8rem;
    line-height: 1.55;
    color: var(--fg-color, #a9b1d6);
}

/* A pinned select is still readable — greying it out to the point of being
   unreadable hides the very answer the note is explaining. */
select:disabled {
    opacity: 0.75;
    cursor: not-allowed;
}

/* ─── Syntax highlighting ─────────────────────────────────────────────────────
   Tokyo Night, using the same --accent-* variables as the rest of the site so a
   code block belongs to the page rather than looking like an embedded widget
   from somewhere else. Applied by highlight.js; every colour here degrades to
   plain monospace text if that file fails to load.

   Contrast: all of these sit on --bg-dark (#13141c) and clear 4.5:1, except
   .tk-comment which is deliberately quieter at ~4.6:1 — a comment that competes
   with the command it explains is worse than one that recedes. */
.tk-comment  { color: #6b7394; font-style: italic; }
.tk-string   { color: var(--accent-green, #9ece6a); }
.tk-keyword  { color: var(--accent-purple, #bb9af7); }
.tk-builtin  { color: var(--accent-blue, #7aa2f7); }
.tk-variable { color: var(--accent-orange, #ff9e64); }
.tk-number   { color: var(--accent-orange, #ff9e64); }
.tk-operator { color: var(--accent-cyan, #7dcfff); }
.tk-flag     { color: var(--accent-yellow, #e0af68); }

.tk-md-head  { color: var(--accent-purple, #bb9af7); font-weight: 700; }
.tk-md-bold  { color: var(--fg-color, #a9b1d6); font-weight: 700; }
.tk-md-em    { color: var(--fg-color, #a9b1d6); font-style: italic; }
.tk-md-code  { color: var(--accent-green, #9ece6a); }
.tk-md-link  { color: var(--accent-blue, #7aa2f7); }
.tk-md-quote { color: var(--accent-cyan, #7dcfff); }
.tk-md-list  { color: var(--accent-orange, #ff9e64); }
.tk-md-table { color: var(--fg-dim, #7f88ad); }
.tk-md-rule  { color: var(--border-color, #2d2d3f); }
.tk-md-fence { color: var(--accent-green, #9ece6a); }

.tk-diff-add { color: var(--accent-green, #9ece6a); }
.tk-diff-del { color: var(--accent-red, #f7768e); }

/* The language label. An attribute on the <pre>, not an element inside it, so
   it can never end up in a copied selection — every copy button on this site
   reads textContent, and "bash" pasted at the top of a script would break it. */
pre.tk {
    position: relative;
}

pre.tk[data-tk-lang]::before {
    content: attr(data-tk-lang);
    position: absolute;
    top: 0;
    right: 0;
    padding: 0.15rem 0.55rem;
    font-family: var(--font-mono);
    font-size: 0.68rem;
    letter-spacing: 0.06em;
    text-transform: lowercase;
    color: var(--fg-dim, #7f88ad);
    background: var(--bg-lighter, #24283b);
    border-left: 1px solid var(--border-color, #2d2d3f);
    border-bottom: 1px solid var(--border-color, #2d2d3f);
    border-radius: 0 6px 0 6px;
    pointer-events: none;
    user-select: none;
}

/* A copy button, where a page has one, sits in the same corner. Move the label
   left so the two do not stack. */
pre.tk:has(.copy-btn)[data-tk-lang]::before { right: 3.2rem; }

@media (max-width: 480px) {
    /* On a phone the label eats a third of a narrow block. The colours already
       say what it is. */
    pre.tk[data-tk-lang]::before { display: none; }
}

/* Respect a reader who has asked for less contrast in their OS. */
@media (prefers-contrast: more) {
    .tk-comment { color: #8b95bd; font-style: normal; }
}

/* Rendered markdown in the Live Editor preview. Previously each element carried
   its own inline colours, copied from GitHub's dark theme rather than taken from
   this palette, so a previewed guide did not look like the site it was on. */
#markdown-preview h1,
#markdown-preview h2,
#markdown-preview h3,
#markdown-preview h4 { color: var(--accent-purple); margin: 1.2rem 0 0.5rem; }
#markdown-preview h1 { font-size: 1.4rem; }
#markdown-preview h2 { font-size: 1.2rem; }
#markdown-preview h3 { font-size: 1.05rem; }
#markdown-preview h4 { font-size: 0.95rem; }
#markdown-preview code {
    background: var(--bg-darker);
    color: var(--accent-green);
    padding: 0.15em 0.4em;
    border-radius: 3px;
    font-family: var(--font-mono);
    font-size: 0.88em;
}
#markdown-preview blockquote {
    border-left: 3px solid var(--accent-purple);
    background: var(--tint-purple, rgba(187, 154, 247, 0.07));
    padding: 0.4rem 0.9rem;
    color: var(--fg-dim);
    margin: 0.6rem 0;
    border-radius: 0 6px 6px 0;
}
#markdown-preview ul { margin: 0.5rem 0 0.5rem 1.3rem; }
#markdown-preview hr { border: 0; border-top: 1px solid var(--border-color); margin: 1.2rem 0; }
#markdown-preview a { color: var(--accent-blue); }

/* A fenced block inside the preview. The <code> keeps its own token colours;
   this is only the frame around it. */
.md-preview-code {
    background: var(--bg-dark);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 1rem;
    margin: 1rem 0;
    overflow-x: auto;
}
/* Inline-code styling must not leak into a fenced block's <code>. */
#markdown-preview .md-preview-code code {
    background: none;
    color: inherit;
    padding: 0;
    font-size: 0.85rem;
}

/* ─── Rendered markdown documents ─────────────────────────────────────────────
   Used by wiki.html?page=, the cheatsheets tabs, and the Live Editor preview.
   These exist because following a docs link used to land the reader on a raw
   .md file — grey serif text, no header, no navigation, no way back. A document
   is part of the site, so it has to look like it. */

.md-alert {
    border-left: 3px solid var(--accent-cyan);
    background: var(--tint-cyan);
    border-radius: 0 8px 8px 0;
    padding: 0.75rem 1rem;
    margin: 1rem 0;
}
.md-alert > p { margin: 0.35rem 0 0; }
.md-alert > p:first-of-type { margin-top: 0.15rem; }
.md-alert-head {
    display: block;
    font-weight: 700;
    font-size: 0.85rem;
    letter-spacing: 0.02em;
    color: var(--accent-cyan);
}

/* One per alert type, so severity is legible before the text is read. */
.md-alert.md-note      { border-left-color: var(--accent-blue);   background: var(--tint-blue); }
.md-alert.md-note      .md-alert-head { color: var(--accent-blue); }
.md-alert.md-tip       { border-left-color: var(--accent-green);  background: var(--tint-green); }
.md-alert.md-tip       .md-alert-head { color: var(--accent-green); }
.md-alert.md-important { border-left-color: var(--accent-purple); background: var(--tint-purple); }
.md-alert.md-important .md-alert-head { color: var(--accent-purple); }
.md-alert.md-warning   { border-left-color: var(--accent-orange); background: var(--tint-orange); }
.md-alert.md-warning   .md-alert-head { color: var(--accent-orange); }
.md-alert.md-caution   { border-left-color: var(--accent-red);    background: var(--tint-red); }
.md-alert.md-caution   .md-alert-head { color: var(--accent-red); }
.md-alert.md-quote     { border-left-color: var(--border-color);  background: transparent; }
.md-alert.md-quote .md-alert-head { display: none; }

.md-code {
    background: var(--bg-dark);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 1rem;
    margin: 1rem 0;
    overflow-x: auto;
    font-size: 0.85rem;
}

.md-tablewrap { overflow-x: auto; margin: 1rem 0; }
.md-table { border-collapse: collapse; width: 100%; font-size: 0.86rem; }
.md-table th,
.md-table td { border: 1px solid var(--border-color); padding: 0.5rem 0.7rem; text-align: left; }
.md-table th { background: var(--bg-lighter); color: var(--accent-cyan); font-weight: 700; }
.md-table tr:nth-child(even) td { background: rgba(255, 255, 255, 0.015); }

/* ─── wiki.html?page= document view ───────────────────────────────────────── */
.wiki-doc { max-width: 100%; }

.wiki-doc-crumbs {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.82rem;
    color: var(--fg-dim);
    padding-bottom: 0.7rem;
    margin-bottom: 1.2rem;
    border-bottom: 1px solid var(--border-color);
}
.wiki-doc-here { color: var(--accent-cyan); font-weight: 700; }

.wiki-doc-body h1 { font-size: 1.55rem; color: var(--heading-color, var(--accent-cyan)); margin: 0 0 0.8rem; }
.wiki-doc-body h2 { font-size: 1.2rem;  color: var(--accent-purple); margin: 1.7rem 0 0.6rem; }
.wiki-doc-body h3 { font-size: 1.02rem; color: var(--accent-cyan);   margin: 1.3rem 0 0.5rem; }
.wiki-doc-body h4 { font-size: 0.94rem; color: var(--accent-green);  margin: 1.1rem 0 0.4rem; }
.wiki-doc-body p  { line-height: 1.75; margin: 0.6rem 0; }
.wiki-doc-body ul,
.wiki-doc-body ol { margin: 0.6rem 0 0.6rem 1.4rem; }
.wiki-doc-body li { margin-bottom: 0.35rem; line-height: 1.7; }
.wiki-doc-body hr { border: 0; border-top: 1px solid var(--border-color); margin: 1.8rem 0; }
.wiki-doc-body img { max-width: 100%; height: auto; border-radius: 8px; }
.wiki-doc-body > :not(.md-code) code {
    background: var(--bg-darker);
    color: var(--accent-green);
    padding: 0.15em 0.4em;
    border-radius: 4px;
    font-family: var(--font-mono);
    font-size: 0.88em;
}
.wiki-doc-body kbd {
    background: var(--bg-lighter);
    border: 1px solid var(--border-color);
    border-bottom-width: 2px;
    border-radius: 4px;
    padding: 0.1em 0.4em;
    font-family: var(--font-mono);
    font-size: 0.85em;
    color: var(--accent-cyan);
}
.wiki-doc-loading { color: var(--fg-dim); font-style: italic; }

/* The document's own contents list, when it has enough headings to need one. */
.wiki-doc-toc {
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 0.8rem 1rem;
    margin: 0 0 1.5rem;
    font-size: 0.84rem;
}
.wiki-doc-toc strong { color: var(--accent-cyan); display: block; margin-bottom: 0.4rem; }
.wiki-doc-toc ul { list-style: none; margin: 0; padding: 0; }
.wiki-doc-toc li { margin-bottom: 0.15rem; }
.wiki-doc-toc li.lvl-3 { padding-left: 1rem; }
.wiki-doc-toc a { color: var(--fg-color); }
.wiki-doc-toc a:hover { color: var(--accent-cyan); }

.wiki-doc-foot {
    display: flex;
    flex-wrap: wrap;
    gap: 1.2rem;
    margin-top: 2.5rem;
    padding-top: 1rem;
    border-top: 1px solid var(--border-color);
    font-size: 0.85rem;
}

@media (pointer: coarse), (max-width: 768px) {
    /* 44px tap targets on the two links out of a document. */
    .wiki-doc-foot a,
    .wiki-doc-crumbs a { display: inline-flex; align-items: center; min-height: var(--tap-target, 44px); }
}

/* A page-specific note that is not a landmark. Four pages carried a second
   hand-styled <footer> alongside the shared one, which gave a screen reader two
   unnamed contentinfo regions to announce. Where the text was page-specific and
   true (the Live Editor's "nothing leaves your browser", the security tools'
   lock-out warning) it moved here; where it duplicated the shared footer — or,
   on the wiki, stated the wrong licence entirely — it was removed. */
.page-note {
    max-width: 90ch;
    margin: 2rem auto 0;
    padding: 0.8rem 1.1rem;
    text-align: center;
    font-size: 0.82rem;
    line-height: 1.65;
    color: var(--fg-dim);
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-radius: 8px;
}
.page-note-warn {
    border-color: var(--accent-red);
    background: var(--tint-red);
    color: var(--fg-color);
}

/* ─── Walkthrough: suggested answers and "how do I find this out?" ────────────
   The disk question used to say "run lsblk" and stop, which is no help if you
   have not read lsblk output before. The time zone had to be typed by hand,
   which on a phone is how people end up with the wrong clock. */
.q-suggest {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-top: 0.6rem;
    background: var(--tint-green);
    border: 1px solid var(--accent-green);
    color: var(--accent-green);
    font-family: var(--font-mono);
    font-size: 0.83rem;
    font-weight: 700;
    padding: 0.4rem 0.85rem;
    border-radius: 8px;
    cursor: pointer;
    min-height: var(--tap-target, 44px);
    transition: filter 0.18s;
}
.q-suggest:hover { filter: brightness(1.14); }
.q-suggest-note { color: var(--fg-dim); font-size: 0.74rem; font-weight: 400; }

.q-howto {
    margin-top: 1rem;
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 0.5rem 0.9rem 0.8rem;
    font-size: 0.82rem;
}
.q-howto[open] { border-color: var(--accent-cyan); }
.q-howto > summary {
    cursor: pointer;
    color: var(--accent-cyan);
    font-family: var(--font-mono);
    font-weight: 700;
    min-height: var(--tap-target, 44px);
    display: flex;
    align-items: center;
    list-style-position: inside;
}
.q-howto-p { margin: 0.5rem 0; line-height: 1.7; color: var(--fg-color); }
.q-howto-cmd {
    background: var(--bg-dark);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 0.7rem 0.9rem;
    margin: 0.5rem 0 0.35rem;
    overflow-x: auto;
    font-size: 0.8rem;
}
.q-howto-copy { font-size: 0.74rem; padding: 0.25rem 0.7rem; min-height: 0; }

/* Device names spelled out, rather than assuming the reader knows why the
   partition suffix has a p in it on one machine and not another. */
.q-howto-naming { margin: 0.8rem 0 0; }
.q-howto-naming dt {
    color: var(--accent-orange);
    font-family: var(--font-mono);
    font-size: 0.8rem;
    font-weight: 700;
    margin-top: 0.55rem;
}
.q-howto-naming dd { margin: 0.15rem 0 0 1.1rem; color: var(--fg-dim); line-height: 1.65; }
.q-howto-warn {
    margin: 0.9rem 0 0;
    padding: 0.55rem 0.8rem;
    background: var(--tint-red);
    border-left: 3px solid var(--accent-red);
    border-radius: 0 6px 6px 0;
    color: var(--fg-color);
    line-height: 1.65;
}
.q-howto-wiki { display: inline-block; margin-top: 0.8rem; font-size: 0.8rem; }

/* ─── Walkthrough: whole guide vs one command at a time ───────────────────────
   One segmented control, not two loose buttons. The first attempt at this
   shipped with no stylesheet at all — a heredoc that wrote it failed on a
   quoting error and the failure was not checked — so it rendered as two default
   browser buttons above the guide, which is why it looked pasted on.

   Each half carries its own accent because the two halves do different things:
   cyan for reading, matching the site's informational surfaces, and green for
   doing, matching every other "go" control here. */
.guide-mode {
    display: flex;
    gap: 0;
    margin-bottom: 1rem;
    padding: 3px;
    background: var(--bg-dark);
    border: 1px solid var(--border-color);
    border-radius: 10px;
}
.guide-mode-btn {
    flex: 1;
    background: transparent;
    border: 1px solid transparent;
    color: var(--fg-dim);
    border-radius: 7px;
    padding: 0.45rem 0.6rem;
    font-family: var(--font-mono);
    font-size: 0.78rem;
    font-weight: 700;
    cursor: pointer;
    min-height: var(--tap-target, 44px);
    transition: background 0.18s, color 0.18s, border-color 0.18s;
}
.guide-mode-btn:hover:not(.active) { color: var(--fg-color); background: var(--bg-lighter); }
#mode-guide.active {
    background: var(--tint-cyan);
    border-color: var(--accent-cyan);
    color: var(--accent-cyan);
}
#mode-commands.active {
    background: var(--tint-green);
    border-color: var(--accent-green);
    color: var(--accent-green);
}

.cmd-progress {
    display: flex;
    justify-content: space-between;
    gap: 0.6rem;
    font-family: var(--font-mono);
    font-size: 0.76rem;
    color: var(--fg-dim);
    margin-bottom: 0.45rem;
}
.cmd-progress-title { color: var(--accent-cyan); text-align: right; font-weight: 700; }

.cmd-card {
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 1rem 1.1rem;
}
/* Red frame for anything that cannot be undone. */
.cmd-card.cmd-danger { border-color: var(--accent-red); background: var(--tint-red); }
.cmd-warn {
    background: var(--bg-dark);
    border-left: 3px solid var(--accent-red);
    border-radius: 0 6px 6px 0;
    padding: 0.6rem 0.85rem;
    margin-bottom: 0.85rem;
    font-size: 0.81rem;
    line-height: 1.65;
}
.cmd-warn strong { color: var(--accent-red); }
.cmd-why { font-size: 0.82rem; color: var(--fg-dim); line-height: 1.75; margin: 0 0 0.75rem; }
.cmd-block {
    background: var(--bg-dark);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 0.9rem 1rem;
    overflow-x: auto;
    font-size: 0.82rem;
    margin: 0 0 0.65rem;
}
.cmd-actions { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 0.75rem; }
.cmd-expected {
    background: var(--tint-green);
    border-left: 3px solid var(--accent-green);
    border-radius: 0 6px 6px 0;
    padding: 0.55rem 0.85rem;
    font-size: 0.81rem;
    line-height: 1.65;
}
.cmd-expected strong { color: var(--accent-green); }
.cmd-confirm-label {
    display: block;
    margin: 1rem 0 0.35rem;
    font-size: 0.81rem;
    color: var(--accent-red);
    font-weight: 700;
    line-height: 1.55;
}
.cmd-nav { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 1rem; }
.cmd-next {
    background: var(--accent-green);
    color: var(--bg-color);
    border: 1px solid var(--accent-green);
    font-weight: 700;
}
.cmd-next:hover { filter: brightness(1.12); }
.cmd-finished {
    margin: 0.95rem 0 0;
    padding: 0.6rem 0.85rem;
    background: var(--tint-cyan);
    border-left: 3px solid var(--accent-cyan);
    border-radius: 0 6px 6px 0;
    font-size: 0.82rem;
    line-height: 1.65;
}

/* Jump list, so you can find your place again after a reboot.

   Solid background, not transparent. It had none, so when open it overlaid the
   guide text behind it and the two sets of words sat on top of each other. A
   list you cannot read is worse than no list. */
.cmd-jump {
    margin-top: 1rem;
    font-size: 0.8rem;
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 0.5rem 0.8rem 0.7rem;
}
.cmd-jump[open] { border-color: var(--accent-cyan); }
.cmd-jump > summary {
    cursor: pointer;
    color: var(--accent-cyan);
    font-family: var(--font-mono);
    min-height: var(--tap-target, 44px);
    display: flex;
    align-items: center;
    list-style-position: inside;
}
.cmd-list {
    list-style: none;
    margin: 0.5rem 0 0;
    padding: 0;
    /* Thirty-odd commands would otherwise push everything below off the page. */
    max-height: 40vh;
    overflow-y: auto;
}
.cmd-list li { margin-bottom: 0.15rem; }
.cmd-list-btn {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: 1px solid transparent;
    border-radius: 6px;
    color: var(--fg-dim);
    font-family: var(--font-mono);
    font-size: 0.78rem;
    padding: 0.4rem 0.6rem;
    cursor: pointer;
    min-height: var(--tap-target, 44px);
    transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.cmd-list-btn:hover { border-color: var(--accent-cyan); color: var(--accent-cyan); }
.cmd-list-btn.danger { color: var(--accent-red); }
.cmd-list li.here > .cmd-list-btn {
    background: var(--tint-cyan);
    border-color: var(--accent-cyan);
    color: var(--accent-cyan);
}
.cmd-list li.done > .cmd-list-btn { color: var(--accent-green); }

/* A plain-text document shown inside the wiki's frame — the waiver and the
   licence. Not run through the markdown renderer: their hard wrapping and
   numbered clauses are load-bearing, and reflowing a legal document is a
   different document. Verbatim, in the site's own typeface and palette, rather
   than the browser's default serif on white. */
.md-plaintext {
    background: var(--bg-dark);
    border: 1px solid var(--border-color);
    border-radius: 8px;
    padding: 1.2rem 1.4rem;
    margin: 0;
    overflow-x: auto;
    font-family: var(--font-mono);
    font-size: 0.82rem;
    line-height: 1.75;
    color: var(--fg-color);
    white-space: pre-wrap;
    word-break: break-word;
}

/* ─── Shared generation-history overlay ───────────────────────────────────────
   Reachable from every page. The clock button used to be created only when
   `window.toggleHistoryModal` existed, and that lives in script.js — so nine of
   eleven pages had no clock and no way to reach the history at all. */
.history-overlay {
    position: fixed;
    inset: 0;
    background: rgba(13, 17, 23, 0.92);
    backdrop-filter: blur(6px);
    z-index: 10001;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding: 4vh 1rem;
    overflow-y: auto;
}
.history-panel {
    background: var(--bg-color);
    border: 1px solid var(--accent-purple);
    border-radius: 14px;
    padding: 1.6rem;
    width: 100%;
    max-width: 680px;
    box-shadow: 0 20px 60px rgba(0, 0, 0, 0.7);
}
.history-head h2 { color: var(--accent-purple); margin: 0 0 0.4rem; font-size: 1.15rem; }
.history-head p { color: var(--fg-dim); font-size: 0.82rem; line-height: 1.65; margin: 0 0 1.1rem; }

.history-list { list-style: none; margin: 0; padding: 0; }
.history-item {
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-radius: 10px;
    padding: 0.8rem 0.95rem;
    margin-bottom: 0.6rem;
}
.history-meta {
    display: flex;
    justify-content: space-between;
    gap: 0.6rem;
    flex-wrap: wrap;
    font-size: 0.82rem;
    margin-bottom: 0.6rem;
}
.history-meta strong { color: var(--accent-cyan); }
.history-meta span { color: var(--fg-dim); font-family: var(--font-mono); font-size: 0.76rem; }
.history-actions { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.history-btn-sm {
    font-size: 0.74rem;
    padding: 0.3rem 0.65rem;
    min-height: 0;
    text-decoration: none;
}
.history-foot { display: flex; justify-content: flex-end; margin-top: 1.1rem; }

@media (pointer: coarse), (max-width: 768px) {
    /* Real tap targets, and a panel that uses the whole screen. */
    .history-panel { max-width: 100%; border-radius: 12px; padding: 1.2rem 1rem; }
    .history-btn-sm { min-height: var(--tap-target, 44px); display: inline-flex; align-items: center; }
}

/* The "report a bug" line in the footer's project block. Slightly separated from
   the credits above it: it is an invitation to act, not more attribution. */
.footer-report {
    border-top: 1px solid var(--border-color);
    padding-top: 0.6rem;
    margin-top: 0.7rem;
    font-size: 0.76rem;
    line-height: 1.6;
}
.footer-report strong { color: var(--accent-orange); }

/* ── Package search ──────────────────────────────────────────────────────────
   Shared by the *nix Install Generator and the *nix Install Walkthrough (pkg-search.js).
   Palette variables only — the palette gate fails on a colour literal here. */

.pkg-search {
    margin-top: 0.75rem;
    border: 1px solid var(--border-color);
    border-radius: 6px;
    background: var(--bg-darker);
    padding: 0.6rem;
}

.pkg-search-row {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.pkg-search-box {
    flex: 1 1 12rem;
    min-width: 0;
    min-height: var(--tap-target, 44px);
    padding: 0.5rem 0.65rem;
    background: var(--bg-color);
    border: 1px solid var(--border-color);
    border-radius: 4px;
    color: var(--fg-color);
    font-family: inherit;
    font-size: 0.9rem;
}

.pkg-search-box:focus {
    outline: none;
    border-color: var(--accent-blue);
}

/* `width: auto` is doing real work here. The generator's `.btn` is full-width
   because it is used for Generate, so without this every button in the row
   claimed 100% and the three of them stacked into a column three rows tall. */
.pkg-search-go,
.pkg-search .pkg-add {
    flex: 0 0 auto;
    width: auto;
    min-height: var(--tap-target, 44px);
    padding-inline: 0.9rem;
    white-space: nowrap;
}

.pkg-search-note {
    margin: 0.35rem 0;
    font-size: 0.8rem;
    color: var(--fg-dim);
}

/* The AUR caveat, kept visually distinct from the neutral explanatory note:
   an AUR PKGBUILD is a build script a stranger wrote that runs as your user,
   and that deserves more than the same grey as everything else. */
.pkg-search-warn { color: var(--accent-orange); }

.pkg-add {
    min-height: var(--tap-target, 44px);
    font-family: var(--font-mono, monospace);
    font-size: 0.85rem;
}

/* Official packages are signed and built by Arch; AUR packages are not. The
   two buttons are coloured to say which is which before anyone clicks.

   The background must be overridden, not just the text colour: `.btn` fills
   with --accent-purple, and accent-green or accent-orange text on that is two
   light colours against each other — it failed to read at all. Outlined on the
   panel background instead, which also keeps these visually secondary to the
   real Generate button. */
.pkg-go-official,
.pkg-go-aur {
    background: var(--bg-color);
    border-width: 1px;
    border-style: solid;
}

.pkg-go-official { border-color: var(--accent-green); color: var(--accent-green); }
.pkg-go-aur      { border-color: var(--accent-orange); color: var(--accent-orange); }

.pkg-go-official:hover { background: var(--tint-green, var(--bg-lighter)); }
.pkg-go-aur:hover      { background: var(--tint-orange, var(--bg-lighter)); }

/* ─── Mobile browser chrome clearance ────────────────────────────────────────
   iOS Safari puts its address bar at the BOTTOM of the screen, overlaying page
   content. Anything sitting at the natural end of the document — on this site
   that is the Generate button, and the Continue button in the walkthrough —
   ends up underneath it and cannot be tapped. Reported from a real iPhone.

   Fixed with scroll clearance rather than `viewport-fit=cover` + full
   safe-area padding. `viewport-fit=cover` would also push content under the
   *top* notch and the side insets, which means auditing all four edges on
   eleven pages to fix one; this solves the reported problem and cannot
   regress the others.

   `env(safe-area-inset-bottom)` is still included and simply resolves to 0px
   without `viewport-fit=cover`, so it costs nothing now and starts helping
   automatically if that is ever added. The 5rem is the real work: Safari's
   bottom bar is roughly 50px, and this clears it with room to spare so the
   button is comfortably reachable rather than flush against the chrome.

   Applied to the scroll container, not to fixed overlays — the history overlay
   has its own inset:0 positioning and must not gain a phantom gap. */
@media (max-width: 900px) {
    body {
        padding-bottom: calc(5rem + env(safe-area-inset-bottom, 0px));
    }

    /* The footer is the true last element, so it carries the clearance when
       present; without this the padding sits below the footer and the footer
       itself is what ends up under the address bar. */
    .site-footer {
        margin-bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    }
}

/* Landscape phones have a much shorter viewport, and the same bar. Slightly
   less clearance because vertical space is scarcer and the bar is thinner. */
@media (max-width: 900px) and (orientation: landscape) {
    body {
        padding-bottom: calc(3.5rem + env(safe-area-inset-bottom, 0px));
    }
}

/* ─── Command-by-command in the Live Editor ──────────────────────────────────
   Same idea as the walkthrough's: one command, why it is there, and whether it
   is the kind that does not ask twice. */
.cmd-empty { color: var(--fg-dim); font-size: 0.85rem; padding: 0.6rem 0; }
.cmd-step {
    background: var(--bg-darker);
    border: 1px solid var(--border-color);
    border-left: 3px solid var(--accent-cyan);
    border-radius: 8px;
    padding: 0.7rem 0.85rem;
    margin-bottom: 0.6rem;
}
.cmd-step.cmd-destructive { border-left-color: var(--accent-red); }
.cmd-head { display: flex; gap: 0.6rem; align-items: baseline; font-size: 0.82rem; margin-bottom: 0.35rem; }
.cmd-head strong { color: var(--accent-cyan); }
.cmd-step.cmd-destructive .cmd-head strong { color: var(--accent-red); }
.cmd-head span { color: var(--fg-dim); }
.cmd-why { font-size: 0.82rem; color: var(--fg-color); line-height: 1.55; margin-bottom: 0.45rem; }
.cmd-warn { font-size: 0.82rem; color: var(--accent-red); line-height: 1.55; margin-bottom: 0.45rem; }
.cmd-code {
    background: var(--bg-dark);
    border: 1px solid var(--border-color);
    border-radius: 6px;
    padding: 0.6rem 0.7rem;
    overflow-x: auto;
    font-size: 0.82rem;
    white-space: pre;
    margin-bottom: 0.45rem;
}

/* A system listed but not yet selectable. Dimmed rather than hidden: knowing
   what is coming is useful, being handed an unfinished guide is not. */
.os-opt-locked { opacity: 0.62; cursor: not-allowed; }
.os-opt-locked:hover { background: transparent; }
.os-choose-locked:hover { filter: none; }
