/* ============================================================================
   Arch Guides Dynamic — 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; }

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%;
    max-width: clamp(320px, 40vw, 480px);
    margin: 0 auto 0.6rem;
    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; }

/* ─── 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. */
#site-byline {
    display: block;
    text-align: center;
    margin: -0.2rem auto 0.5rem;
    font-size: 0.78rem;
    letter-spacing: 0.03em;
    color: var(--accent-green);
    text-decoration: none;
}
#site-byline:hover { color: var(--accent-cyan); text-decoration: underline; }

/* 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; }

/* 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; }
    /* 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 */
}

/* 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 Dynamic Generator when the chosen desktop only runs on one
   display server. Matches .q-locked in the Manual 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); }
