:root {
    /* Catppuccin Latte palette — the project's canonical color set.
       Reference these instead of raw hex for any new color work. */
    --ctp-rosewater: #dc8a78; --ctp-flamingo: #dd7878; --ctp-pink: #ea76cb;
    --ctp-mauve: #8839ef;     --ctp-red: #d20f39;      --ctp-maroon: #e64553;
    --ctp-peach: #fe640b;     --ctp-yellow: #df8e1d;   --ctp-green: #40a02b;
    --ctp-teal: #179299;      --ctp-sky: #04a5e5;      --ctp-sapphire: #209fb5;
    --ctp-blue: #1e66f5;      --ctp-lavender: #7287fd;
    --ctp-text: #4c4f69;      --ctp-subtext1: #5c5f77; --ctp-subtext0: #6c6f85;
    --ctp-overlay2: #7c7f93;  --ctp-overlay1: #8c8fa1; --ctp-overlay0: #9ca0b0;
    --ctp-surface2: #acb0be;  --ctp-surface1: #bcc0cc; --ctp-surface0: #ccd0da;
    --ctp-base: #eff1f5;      --ctp-mantle: #e6e9ef;   --ctp-crust: #dce0e8;

    --gnome-blue: #1e66f5;
    --font-main: 'Space Grotesk', sans-serif;
    --font-header: 'Architects Daughter', cursive;
    --window-bg: #FAF9F6;
    --accent-lime: #40a02b;
    --accent-lavender: #7287fd;
    --accent-yellow: #df8e1d;
    --accent-sage: #179299;
    --dock-offset: 7.5rem;
    --border-black: 2px solid #000;
}

body {
    font-family: var(--font-main);
    /* Fallback must match the SVG's lavender fill: it flashes before the image
       paints, and iOS Safari samples it for the toolbar tint and overscroll. */
    background-color: #7287fd;
    background-image: url('assets/images/background.svg');
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
    overflow: hidden;
    user-select: none;
    color: #000;
}

/* Interactive elements override the inherited custom arrow with the system
   finger pointer on hover. Non-interactive surfaces keep the themed arrow. */
/* Custom themed select cursor; hotspot at the fingertip, with the system
   pointer as fallback. !important is needed to override Tailwind's CDN-injected
   .cursor-pointer utility (same specificity, injected after this sheet) and the
   class-level .win-ctrl / .brutalist-button rules. */
/* Themed cursors only on real pointing devices — never on touch, where they're
   dead weight and can suppress the native tap behavior. */
@media (hover: hover) and (pointer: fine) {
    body { cursor: url('assets/images/cursor.svg') 13 10, auto; }
    button, a, .cursor-pointer, .win-ctrl, .brutalist-button {
        cursor: url('assets/images/select.svg') 21 13, pointer !important;
    }

    /* Text cursor only over actual text. `cursor` inherits, so a beam on the
       whole content box would bleed onto empty margins and layout gaps. Instead
       the content box keeps the arrow and the beam is applied to text-bearing
       elements only; interactive elements keep the pointer (rule above). The
       light/dark variant is chosen per surface: `.on-dark` uses the white beam,
       everything else the dark one. Terminal and `<pre>` are contiguous text
       surfaces, so the `.on-dark` element itself carries the beam edge to edge;
       document windows only light up their text. The `.on-dark :is(...)` list
       ties `.window-content :is(...)` on specificity and, coming later, wins —
       so text inside a dark surface (e.g. inline <code> in a code block) gets
       the light beam instead of the dark one. */
    .window-content { cursor: url('assets/images/cursor.svg') 13 10, auto; }
    .window-content :is(p, h1, h2, h3, h4, h5, h6, li, dt, dd, label,
        blockquote, th, td, code, input, textarea) {
        cursor: url('assets/images/text-cursor-dark.svg') 18 18, text;
    }
    .on-dark,
    .on-dark :is(p, h1, h2, h3, h4, h5, h6, li, dt, dd, label,
        blockquote, th, td, code, input, textarea) {
        cursor: url('assets/images/text-cursor.svg') 18 18, text;
    }
    /* Images can sit inside a text element (e.g. a KnowledgeBase figure in a <p>) but
       aren't text; keep the arrow over them. */
    .window-content img { cursor: url('assets/images/cursor.svg') 13 10, auto; }
}

/* Visible keyboard focus on interactive elements. Overrides Tailwind's
   `outline-none` on the contact inputs; mouse clicks don't trigger it. */
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible, select:focus-visible,
.kb-row:focus-visible, .kb-caret:focus-visible, .kb-switcher-btn:focus-visible, .kb-switcher-item:focus-visible {
    outline: 3px solid var(--ctp-mauve) !important;
    outline-offset: 2px;
    border-radius: 6px;
}

/* The terminal input has its own blinking caret, so suppress the focus outline. */
#term-input:focus, #term-input:focus-visible {
    outline: none !important;
}

/* Selection model. `body` is user-select: none so the desktop chrome — dock,
   icons, window titles, resize handles — never smears a highlight when dragged.
   Window content opts back in and its children inherit, making everything an
   app renders selectable and copyable. On iOS an input/textarea with
   -webkit-user-select: none won't accept text or raise the keyboard, so editable
   fields re-enable it even outside a window. */
.window-content, input, textarea {
    -webkit-user-select: text;
    user-select: text;
}
/* Drag surfaces inside a window stay unselectable: a slow drag on the header or
   a resizer would otherwise start selecting the title bar. */
.window-header, .resizer {
    -webkit-user-select: none;
    user-select: none;
}

/* The default highlight is browser-blue and washes out on the near-black KB
   code blocks. Lavender reads on light surfaces; green reads on the dark
   #0f172a code block (the only remaining .on-dark surface). */
::selection { background: var(--accent-lavender); color: #000; }
.on-dark ::selection, .on-dark::selection { background: var(--accent-lime); color: #000; }

/* Keep the dock app-open dot and hover tooltip hidden by default via static CSS
   (not the Tailwind runtime), so they don't flash visible before the CDN loads. */
.dock-dot, .dock-tooltip { opacity: 0; transition: opacity 0.15s ease; }
.group:hover .dock-tooltip { opacity: 1; }

/* Boot fade-in: show only the background briefly on load, then ease everything in. */
.boot-fade { transition: opacity 0.5s ease; }
body.booting .boot-fade { opacity: 0; }

.arch-font { font-family: var(--font-header); }
.ubuntu-reg { font-family: var(--font-main); font-weight: 400; }
.ubuntu-bold { font-family: var(--font-main); font-weight: 700; }

.window-frame {
    position: absolute;
    background-color: var(--window-bg);
    border-radius: 16px;
    display: flex;
    flex-direction: column;
    transition: transform 0.2s, opacity 0.2s, box-shadow 0.2s ease;
    border: var(--border-black);
    /* No shadow by default — an unfocused window sits flat. The offset shadow
       is a marker of "this is the window you're working in" and only appears on
       the focused window (see .window-frame.focused), revealed by the box-shadow
       transition above as focus lands. */
    box-shadow: 0px 0px 0px #000;
}

/* The window in the user's current context: the offset shadow slides out from
   under the frame as it takes focus. */
.window-frame.focused {
    box-shadow: 4px 4px 0px #000;
}

.window-frame.fs-anim {
    transition: top 0.25s ease, left 0.25s ease, width 0.25s ease, height 0.25s ease, border-radius 0.25s ease, box-shadow 0.25s ease, border 0.25s ease;
}


.window-inner {
    position: relative;
    display: flex;
    flex-direction: column;
    height: 100%;
    width: 100%;
    overflow: hidden;
    border-radius: 14px;
}

.window-header {
    height: 3.5rem;
    background-color: var(--accent-lavender);
    border-bottom: var(--border-black);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 2.25rem;
    cursor: grab;
    flex-shrink: 0;
    /* Let pointer-based dragging work on touch devices (tablets) without the
       browser treating the drag as a scroll/pan gesture. */
    touch-action: none;
}

.win-ctrl {
    width: 2rem;
    height: 2rem;
    border-radius: 8px;
    border: 2px solid #000;
    background-color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
    color: #000;
    font-weight: 900;
    transition: all 0.1s;
}

.win-ctrl:active {
    transform: translate(1px, 1px);
}

.win-ctrl-close:hover { background: #d20f39; color: #fff; }
.win-ctrl-max:hover { background: var(--accent-lime); }
.win-ctrl-min:hover { background: var(--accent-yellow); }

.maximized {
    top: 16px !important;
    left: 16px !important;
    width: calc(100vw - 32px) !important;
    height: calc(100vh - var(--dock-offset) - 16px) !important;
    transform: none !important;
}

.maximized .resizer { display: none; }
.maximized .window-header { cursor: default !important; }

.minimized { opacity: 0; transform: translateY(100px) scale(0.8); pointer-events: none; }

.window-frame.snapping {
    transition: top 0.2s ease, left 0.2s ease, width 0.2s ease, height 0.2s ease, border-radius 0.2s ease;
}

.snap-preview {
    position: fixed;
    background: rgba(114, 135, 253, 0.25);
    border: 2px dashed #000;
    border-radius: 16px;
    z-index: 99;
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.15s ease, top 0.15s ease, left 0.15s ease, width 0.15s ease, height 0.15s ease;
}

.snap-preview.visible { opacity: 1; }

.brutalist-card {
    background: #fff;
    border: var(--border-black);
    border-radius: 12px;
    transition: transform 0.1s;
}

.brutalist-card:hover {
    transform: translate(-2px, -2px);
}

/* Shadow steps match the "Begin Journey!" CTA so the two primary buttons press
   identically: the offset grows on hover and collapses as the button sinks. */
.brutalist-button {
    background: var(--accent-lime);
    border: var(--border-black);
    border-radius: 8px;
    padding: 0.5rem 1.5rem;
    font-weight: 700;
    box-shadow: 3px 3px 0 #000;
    transition: all 0.1s;
    cursor: pointer;
}

.brutalist-button:hover {
    transform: translate(-1px, -1px);
    box-shadow: 4px 4px 0 #000;
}

.brutalist-button:active {
    transform: translate(2px, 2px);
    box-shadow: none;
}

.custom-scroll::-webkit-scrollbar { width: 12px; }
.custom-scroll::-webkit-scrollbar-track { background: #fff; border-left: var(--border-black); }
.custom-scroll::-webkit-scrollbar-thumb { background: #000; border: 3px solid #fff; }

.animate-pop { animation: brutalPop 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275); }
@keyframes brutalPop { from { opacity: 0; transform: scale(0.9) translateY(20px); } to { opacity: 1; transform: scale(1) translateY(0); } }
/* Closing mirrors the open pop in reverse: fade + shrink + settle downward, so a
   window leaves as smoothly as it arrives. `forwards` holds the end state until
   closeWindow removes the element on animationend. */
.animate-pop-out { animation: brutalPopOut 0.22s cubic-bezier(0.32, 0, 0.67, 0) forwards; pointer-events: none; }
@keyframes brutalPopOut { from { opacity: 1; transform: scale(1) translateY(0); } to { opacity: 0; transform: scale(0.9) translateY(20px); } }

.icon-label { font-size: 0.85rem; font-weight: 400; color: #fff; }

/* Rubber-band selection drawn when dragging across the empty desktop. The box
   sits above the icons (z-0) but below windows (z-10), and never eats clicks. */
.marquee-box {
    position: absolute;
    z-index: 5;
    pointer-events: none;
    border: 2px solid var(--gnome-blue);
    background: rgba(30, 102, 245, 0.18);
    border-radius: 4px;
}
/* Icons the marquee overlaps get a translucent highlight (background only, so
   it doesn't shift layout). */
#app-grid > div.marquee-selected {
    background: rgba(30, 102, 245, 0.25);
    border-radius: 12px;
}

.view-section { display: none; height: 100%; flex-direction: column; }
.view-section.active { display: flex; }

/* RESIZERS */
.resizer { position: absolute; z-index: 100; touch-action: none; }
.resizer-n { top: -4px; left: 10px; right: 10px; height: 10px; cursor: n-resize; }
.resizer-s { bottom: -4px; left: 10px; right: 10px; height: 10px; cursor: s-resize; }
.resizer-e { top: 10px; bottom: 10px; right: -4px; width: 10px; cursor: e-resize; }
.resizer-w { top: 10px; bottom: 10px; left: -4px; width: 10px; cursor: w-resize; }
.resizer-ne { top: -4px; right: -4px; width: 16px; height: 16px; cursor: ne-resize; z-index: 101; }
.resizer-nw { top: -4px; left: -4px; width: 16px; height: 16px; cursor: nw-resize; z-index: 101; }
.resizer-se { bottom: -4px; right: -4px; width: 16px; height: 16px; cursor: se-resize; z-index: 101; }
.resizer-sw { bottom: -4px; left: -4px; width: 16px; height: 16px; cursor: sw-resize; z-index: 101; }

/* ============================================================
   DESKTOP READABILITY
   Nudge the running body copy inside windows up a step for
   readability. Scoped to >=768px so the phone tier's own
   carefully-tuned compact scale (below) is left untouched.
   ============================================================ */
@media (min-width: 768px) {
    /* Unclassed paragraph text falls back to the 16px body size. */
    .window-inner { font-size: 1.125rem; }
    .window-inner .text-sm { font-size: 1rem; line-height: 1.5rem; }
    .window-inner .text-base { font-size: 1.1875rem; }
    .window-inner .text-lg { font-size: 1.25rem; }
}

/* ============================================================
   KNOWLEDGE BASE (docs app)
   PostHog-style docs: a card landing grouped by domain, and an
   article view with a sidebar nav tree, content, and a TOC.
   Scoped under .kb so it never leaks into other app windows.
   ============================================================ */
.kb { height: 100%; width: 100%; color: #000; }
.kb .custom-scroll { scrollbar-width: thin; }

/* --- Landing --- */
.kb-landing { height: 100%; overflow-y: auto; padding: 2rem 2.25rem 3rem; }
.kb-hero { margin-bottom: 1.5rem; }
.kb-hero h2 { font-size: 2rem; line-height: 1.1; }
.kb-hero p { color: #5c5f77; margin-top: 0.4rem; }

.kb-search {
    width: 100%;
    padding: 0.75rem 1rem;
    border: var(--border-black);
    border-radius: 10px;
    background: #fff;
    box-shadow: 3px 3px 0 #000;
    margin-bottom: 2rem;
    font-size: 1rem;
}
.kb-search:focus { outline: none; transform: translate(-1px, -1px); box-shadow: 4px 4px 0 #000; }

.kb-domains { display: flex; flex-direction: column; gap: 2rem; }
.kb-domain-head { display: flex; align-items: baseline; gap: 0.6rem; margin-bottom: 0.85rem; }
.kb-domain-head h3 { font-size: 1.15rem; }
.kb-domain-blurb { color: #6c6f85; font-size: 0.9rem; }

.kb-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 1rem; }
.kb-card {
    text-align: left;
    display: flex; flex-direction: column; gap: 0.35rem;
    padding: 1rem 1.1rem;
    background: #fff;
    border: var(--border-black);
    border-radius: 12px;
    box-shadow: 3px 3px 0 #000;
    border-top: 5px solid var(--kb-accent, var(--accent-lime));
    transition: transform 0.1s, box-shadow 0.1s;
}
.kb-card:hover { transform: translate(-2px, -2px); box-shadow: 5px 5px 0 #000; }
.kb-card:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 #000; }
.kb-card-title { font-size: 1rem; }
.kb-card-summary { color: #6c6f85; font-size: 0.85rem; line-height: 1.35; }
.kb-noresults { color: #6c6f85; margin-top: 1.5rem; text-align: center; }

/* Landing hub: one big button per domain */
.kb-home { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem; }
.kb-domain-btn {
    text-align: left;
    display: flex; flex-direction: column; gap: 0.4rem;
    padding: 1.4rem 1.4rem 1.2rem;
    background: #fff;
    border: var(--border-black);
    border-radius: 14px;
    box-shadow: 3px 3px 0 #000;
    border-top: 6px solid var(--kb-accent, var(--accent-lime));
    transition: transform 0.1s, box-shadow 0.1s;
}
.kb-domain-btn:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 #000; }
.kb-domain-btn:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 #000; }
.kb-domain-btn-title { font-size: 1.5rem; line-height: 1.1; }
.kb-domain-btn-blurb { color: #6c6f85; font-size: 0.9rem; line-height: 1.4; }
.kb-domain-btn-count {
    color: #9ca0b0; font-size: 0.75rem; text-transform: uppercase;
    letter-spacing: 0.05em; margin-top: 0.3rem;
}

/* --- Article view: sidebar | content | toc --- */
.kb-article-view { display: grid; grid-template-columns: 240px minmax(0, 1fr) 210px; height: 100%; position: relative; }
/* The mobile drawer toggle + backdrop only exist on phones (see mobile block). */
.kb-nav-toggle, .kb-backdrop { display: none; }
.kb-sidebar { border-right: var(--border-black); overflow-y: auto; padding: 1.5rem 1rem; background: #fff; }
.kb-content { overflow-y: auto; padding: 1.5rem 2.25rem 3rem; min-width: 0; }
.kb-toc { border-left: var(--border-black); overflow-y: auto; padding: 1.5rem 1rem; background: #fff; }
.kb-toc.empty { visibility: hidden; }

/* Domain switcher (PostHog-style master dropdown) */
.kb-switcher { position: relative; margin-bottom: 1.25rem; }
.kb-switcher-btn {
    width: 100%; display: flex; align-items: center; justify-content: space-between;
    gap: 0.5rem; padding: 0.55rem 0.8rem; font-size: 0.95rem;
    background: #fff; border: var(--border-black); border-radius: 10px;
    box-shadow: 2px 2px 0 #000;
}
.kb-switcher-btn:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 #000; }
.kb-switcher-caret { font-size: 0.7rem; }
.kb-switcher-menu {
    position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20;
    list-style: none; margin: 0; padding: 0.3rem;
    background: #fff; border: var(--border-black); border-radius: 10px;
    box-shadow: 3px 3px 0 #000;
}
.kb-switcher-item {
    display: block; width: 100%; text-align: left;
    padding: 0.4rem 0.6rem; border-radius: 6px; font-size: 0.9rem; color: #4c4f69;
}
.kb-switcher-item:hover { background: rgba(0,0,0,0.06); }
.kb-switcher-item.active { font-weight: 700; }

/* Collapsible nav tree (nests to any depth via --kb-depth) */
.kb-tree-list { list-style: none; margin: 0; padding: 0; }
.kb-branch-row { display: flex; align-items: center; }
.kb-caret {
    flex-shrink: 0; width: 1.1rem; height: 1.1rem; margin-right: 0.15rem;
    display: flex; align-items: center; justify-content: center;
    color: #6c6f85; transition: transform 0.15s ease;
}
/* Chevron drawn in CSS so there's no icon dependency. */
.kb-caret::before { content: "›"; font-size: 1rem; line-height: 1; font-weight: 700; }
.kb-branch.open > .kb-branch-row > .kb-caret { transform: rotate(90deg); }
/* Collapsed branches hide their children. */
.kb-branch > .kb-tree-list { display: none; }
.kb-branch.open > .kb-tree-list { display: block; }

.kb-row {
    display: block; width: 100%; text-align: left;
    padding: 0.3rem 0.5rem; border-radius: 6px;
    color: #5c5f77; font-size: 0.9rem; line-height: 1.3;
    border-left: 3px solid transparent;
    /* Indent grows one step per nesting level. */
    padding-left: calc(0.5rem + var(--kb-depth, 0) * 0.85rem);
}
.kb-branch-toggle { color: #4c4f69; }
.kb-branch-row .kb-row { flex: 1; }
/* Leaves have no caret, so add its width back to keep text aligned with the
   branch labels above them. */
.kb-leaf > .kb-row { padding-left: calc(1.75rem + var(--kb-depth, 0) * 0.85rem); }
.kb-row:hover { background: rgba(0,0,0,0.05); color: #000; }
.kb-nav-link.active {
    background: var(--kb-accent, var(--accent-lime));
    color: #000; font-weight: 700;
    border-left-color: #000;
}

.kb-back {
    background: #fff; border: var(--border-black); border-radius: 8px;
    padding: 0.3rem 0.8rem; font-size: 0.85rem; margin-bottom: 1.25rem;
    box-shadow: 2px 2px 0 #000;
}
.kb-back:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 #000; }

.kb-toc-title { font-size: 0.8rem; text-transform: uppercase; letter-spacing: 0.05em; color: #9ca0b0; margin-bottom: 0.6rem; }
.kb-toc-list { list-style: none; margin: 0; padding: 0; }
.kb-toc-list a { display: block; color: #5c5f77; font-size: 0.85rem; padding: 0.2rem 0; line-height: 1.3; }
.kb-toc-list a:hover { color: #000; }
.kb-toc-l3 a { padding-left: 0.85rem; font-size: 0.8rem; color: #6c6f85; }

.kb-loading, .kb-error { color: #6c6f85; }

/* --- Rendered markdown --- */
.kb-doc { font-size: 1rem; line-height: 1.65; color: #4c4f69; max-width: 46rem; }
.kb-doc h1 { font-size: 1.85rem; font-weight: 700; line-height: 1.15; margin: 0 0 1rem; }
.kb-doc h2 { font-size: 1.35rem; font-weight: 700; margin: 2rem 0 0.75rem; padding-bottom: 0.3rem; border-bottom: 2px solid #00000018; }
.kb-doc h3 { font-size: 1.1rem; font-weight: 700; margin: 1.5rem 0 0.5rem; }
.kb-doc p { margin: 0 0 1rem; }
.kb-doc ul, .kb-doc ol { margin: 0 0 1rem; padding-left: 1.4rem; }
.kb-doc li { margin: 0.25rem 0; }
.kb-doc a { color: #1e66f5; text-decoration: underline; }
.kb-doc code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.875em; background: #e6e9ef; padding: 0.15em 0.4em;
    border-radius: 5px; border: 1px solid #00000012;
}
.kb-doc pre {
    background: #0f172a; border: var(--border-black); border-radius: 10px;
    padding: 1rem 1.1rem; overflow-x: auto; margin: 0 0 1.25rem;
    box-shadow: 3px 3px 0 #000;
}
.kb-doc pre code { background: none; border: none; padding: 0; font-size: 0.85rem; color: #e2e8f0; }
.kb-doc blockquote {
    margin: 0 0 1.25rem; padding: 0.6rem 1rem;
    border-left: 4px solid var(--accent-yellow);
    background: #e6e9ef; border-radius: 0 8px 8px 0;
}
.kb-doc blockquote p { margin: 0; }
/* Tables sit in a scroll container so wide ones scroll instead of overflowing. */
.kb-table-wrap { overflow-x: auto; margin: 0 0 1.25rem; -webkit-overflow-scrolling: touch; }
.kb-doc table { border-collapse: collapse; width: 100%; margin: 0; font-size: 0.9rem; }
.kb-doc th, .kb-doc td { border: 1px solid #00000020; padding: 0.5rem 0.75rem; text-align: left; }
.kb-doc th { background: #e6e9ef; font-weight: 700; }
.kb-doc tr:nth-child(even) td { background: #eff1f5; }
/* Images (jpeg / png / svg) — responsive block, on-brand framing. */
.kb-doc img {
    display: block;
    max-width: 100%;
    height: auto;
    margin: 1.25rem 0;
    border: var(--border-black);
    border-radius: 10px;
    box-shadow: 3px 3px 0 #000;
    background: #fff;
}

/* ============================================================
   BLOG
   Landing = KnowledgeBase-style hero (hero + search + category cards)
   stacked above a PostHog-inspired posts table rendered as
   neobrutalist "dossier" rows (category-colored left bar).
   The post reading view reuses .kb-doc / .kb-toc, so only
   the surrounding chrome is styled here.
   Scoped under .blog so it never leaks into other app windows.
   ============================================================ */
.blog { height: 100%; width: 100%; color: #000; }
.blog .custom-scroll { scrollbar-width: thin; }

/* --- Landing: hero + search --- */
.blog-landing { height: 100%; overflow-y: auto; padding: 2rem 2.25rem 3rem; }
.blog-hero { margin-bottom: 1.5rem; }
.blog-hero h2 { font-size: 2rem; line-height: 1.1; }
.blog-hero p { color: #5c5f77; margin-top: 0.4rem; }
.blog-search {
    width: 100%; padding: 0.85rem 1.1rem; margin-bottom: 1.5rem;
    font-size: 1rem; background: #fff; color: #000;
    border: var(--border-black); border-radius: 12px;
    box-shadow: 2px 2px 0 #000; transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.blog-search:focus { outline: none; transform: translate(-1px, -1px); box-shadow: 4px 4px 0 #000; }

/* --- Landing: category cards (mirror the KnowledgeBase domain buttons) --- */
.blog-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; margin-bottom: 2.5rem; }
.blog-cat-card {
    text-align: left; display: flex; flex-direction: column; gap: 0.35rem;
    padding: 1.15rem 1.25rem; background: #fff; cursor: pointer;
    border: var(--border-black); border-radius: 14px;
    border-top: 6px solid var(--blog-accent, var(--accent-lime));
    box-shadow: 3px 3px 0 #000; transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.blog-cat-card:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 #000; }
.blog-cat-card:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 #000; }
.blog-cat-title { font-size: 1.25rem; line-height: 1.1; }
.blog-cat-blurb { color: #6c6f85; font-size: 0.85rem; line-height: 1.35; }
.blog-cat-count {
    margin-top: 0.25rem; font-size: 0.7rem; text-transform: uppercase;
    letter-spacing: 0.06em; color: #9ca0b0;
}

/* --- Posts table --- */
.blog-table-head {
    display: flex; align-items: center; justify-content: space-between;
    gap: 1rem; margin-bottom: 0.85rem; padding-bottom: 0.5rem;
    border-bottom: var(--border-black);
}
.blog-table-title { font-family: monospace; font-size: 0.95rem; letter-spacing: -0.01em; }
.blog-table-controls { display: flex; align-items: center; gap: 0.6rem; }
.blog-filter-chip {
    font-size: 0.75rem; padding: 0.3rem 0.6rem; cursor: pointer; color: #000;
    background: var(--blog-accent, #fff); border: var(--border-black);
    border-radius: 999px; box-shadow: 2px 2px 0 #000;
}
.blog-filter-chip:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 #000; }
.blog-sort {
    font-size: 0.8rem; padding: 0.35rem 0.7rem; cursor: pointer; background: #fff;
    border: var(--border-black); border-radius: 8px; box-shadow: 2px 2px 0 #000;
}
.blog-sort:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 #000; }

.blog-rows { display: flex; flex-direction: column; gap: 0.85rem; }
.blog-row {
    display: grid; grid-template-columns: 7.5rem minmax(0, 1fr) auto; align-items: center;
    gap: 1rem; width: 100%; text-align: left; cursor: pointer;
    padding: 0.9rem 1.1rem; background: #fff;
    border: var(--border-black); border-left: 7px solid var(--blog-accent, #000);
    border-radius: 12px; box-shadow: 3px 3px 0 #000;
    transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.blog-row:hover { transform: translate(-2px, -2px); box-shadow: 6px 6px 0 #000; }
.blog-row:active { transform: translate(1px, 1px); box-shadow: 1px 1px 0 #000; }
.blog-row-date { color: #6c6f85; font-size: 0.8rem; font-family: monospace; }
.blog-row-main { display: flex; flex-direction: column; gap: 0.15rem; min-width: 0; }
.blog-row-title { font-size: 1.05rem; line-height: 1.25; }
.blog-row-cat { font-size: 0.78rem; color: var(--blog-accent, #6c6f85); filter: brightness(0.7); font-weight: 700; }
.blog-row-thumb {
    width: 68px; height: 48px; object-fit: cover; display: block;
    border: var(--border-black); border-radius: 8px; background: #fff;
}
.blog-noresults { color: #6c6f85; margin-top: 1.5rem; text-align: center; }

/* --- Post reading view (2-col: body + TOC; reuses .kb-doc/.kb-toc) --- */
.blog-post-view { display: grid; grid-template-columns: minmax(0, 1fr) 210px; height: 100%; }
.blog-back {
    display: inline-block; margin-bottom: 1.25rem; padding: 0.4rem 0.8rem;
    background: #fff; border: var(--border-black); border-radius: 8px;
    box-shadow: 2px 2px 0 #000; cursor: pointer; font-size: 0.85rem;
    transition: transform 0.1s ease, box-shadow 0.1s ease;
}
.blog-back:hover { transform: translate(-1px, -1px); box-shadow: 3px 3px 0 #000; }
.blog-post-header { margin-bottom: 1.5rem; }
.blog-post-cat {
    display: inline-block; padding: 0.2rem 0.65rem; margin-right: 0.6rem; color: #000;
    font-size: 0.75rem; border: var(--border-black); border-radius: 999px; box-shadow: 2px 2px 0 #000;
}
.blog-post-date { color: #6c6f85; font-size: 0.85rem; }
.blog-post-header h1 { font-size: 2rem; line-height: 1.1; margin-top: 0.85rem; }

/* ============================================================
   MOBILE OS LAYOUT (phones)
   Desktop (>=768px) is completely untouched. On phones we turn
   the desktop into a mobile home screen: a grid of app icons,
   a slimmed-down dock, and apps that open as full-screen sheets.
   ============================================================ */
@media (max-width: 767px) {
    /* Push the wallpaper mascot down into the lower third so it clears the two
       icon rows. The background SVG is 16:9; on a tall phone `cover` maps the
       full image height to the viewport (mascot ends up mid-screen, colliding
       with row 2). Slightly over-scaling the height and pinning to the top
       moves the centered mascot downward without exposing any gap (the SVG's
       own cream fill matches the body background). */
    body { background-size: auto 124%; background-position: center top; }

    /* Safe-area insets: keep the dock, copyright, and window sheet clear of the
       notch and home indicator on modern phones (no-ops on the SE, where the
       insets are 0). Requires viewport-fit=cover on the viewport meta. */
    #dock-bar { bottom: calc(1.5rem + env(safe-area-inset-bottom)); }
    #copyright { bottom: calc(0.2rem + env(safe-area-inset-bottom)); }

    /* Desktop icon column -> centered home-screen app grid. */
    #app-grid {
        /* Sits high so both icon rows stay above the (lowered) mascot. */
        top: 0.75rem;
        left: 0;
        right: 0;
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 1.5rem 0.5rem;
        place-items: center;
        padding: 1.5rem 2.25rem;
    }
    #app-grid > div { width: 6rem; }

    /* Dock: shrink the pill + icons to fit a phone screen. */
    #dock { gap: 0.5rem; padding: 0.5rem 0.85rem; }
    #dock-apps { gap: 0.25rem; }
    /* No !important: the ID selector already outranks Tailwind's .w-12/.h-12,
       and !important would block the inline width animation used to smoothly
       grow/collapse dock items (otherwise the dock snaps shut on close). */
    #dock-apps button { width: 2.75rem; height: 2.75rem; }
    #dock-apps button img { width: 1.85rem; height: 1.85rem; }
    /* The active-app dot's default -bottom-2 (-0.5rem) lands on the dock pill's
       border once the dock padding shrinks; lift it up for clearance. */
    #dock-apps .dock-dot { bottom: -0.2rem; }
    /* Hover-only affordances aren't useful on touch. */
    #dock-apps .dock-tooltip { display: none; }

    /* Copyright: shrink and tuck into the corner beneath the dock's bottom edge
       (the centered dock pill would otherwise overlap the left-aligned text). */
    #copyright {
        bottom: 0.2rem;
        left: 0.4rem;
        font-size: 8px;
        letter-spacing: normal;
    }

    /* Apps open as full-screen sheets above the dock.
       !important overrides the per-window inline px sizing from JS. */
    .window-frame {
        top: calc(3rem + env(safe-area-inset-top)) !important;
        left: 0.5rem !important;
        width: calc(100vw - 1rem) !important;
        height: calc(100dvh - 3rem - 6rem - env(safe-area-inset-top) - env(safe-area-inset-bottom)) !important;
        border-radius: 16px !important;
        transform: none;
    }
    .window-inner { border-radius: 14px; }
    .window-header { height: 3rem; padding: 0 1.25rem; cursor: default; }

    /* App content was authored for ~850px windows. On phones we scale the type
       and spacing down and let inner cards run full-width, so everything fits
       on one screen without scrolling. */
    .window-inner * { overflow-wrap: break-word; }
    .window-inner .flex > div { min-width: 0; }

    /* Type scale — compact for phones */
    .window-inner :is(h1, h2, .text-4xl) { font-size: 1.1rem !important; line-height: 1.2; }
    .window-inner .text-3xl { font-size: 1.05rem !important; }
    .window-inner .text-2xl { font-size: 1rem !important; }
    .window-inner :is(.text-xl, .text-lg) { font-size: 0.95rem !important; }
    .window-inner .text-base { font-size: 0.85rem !important; }
    .window-inner .text-sm { font-size: 0.8rem !important; }
    .window-inner .text-xs { font-size: 0.7rem !important; }
    .window-inner .text-7xl { font-size: 2rem !important; }
    .window-inner img[alt="Cyber Dojo"] { height: 2rem !important; }

    /* Inner cards run full-width with tighter padding */
    .window-inner :is(.max-w-3xl, .max-w-lg, .max-w-sm) { max-width: 100% !important; }
    .window-inner .p-8 { padding: 1.25rem !important; }
    .window-inner .p-6 { padding: 1rem !important; }
    .window-inner .px-4 { padding-left: 0 !important; padding-right: 0 !important; }
    .window-inner .px-8 { padding-left: 1.1rem !important; padding-right: 1.1rem !important; }

    /* Trim the large vertical rhythm; keep top padding equal to the p-8 bottom
       so the content's top/bottom padding stays symmetric. */
    .window-inner .pt-20 { padding-top: 1.25rem !important; }
    /* Vertically center top-aligned content (Home) so it isn't all pinned to
       the top with a big empty gap below. */
    .window-inner .justify-start { justify-content: center !important; }
    .window-inner .mt-16 { margin-top: 1rem !important; }
    .window-inner :is(.mb-8, .mb-6) { margin-bottom: 0.75rem !important; }
    .window-inner .h-24 { height: auto !important; }

    /* Files grid: tighten the icon spacing. */
    .window-inner .gap-6 { gap: 0.75rem; }
    /* Course cards (Home + Courses) stack vertically on phones — art on top,
       text and CTA centered below. Cap the art to a comfortable hero size. */
    .window-inner .w-44.h-44 { width: 9rem !important; height: 9rem !important; }

    /* Center everything within windows on mobile. */
    .window-inner { text-align: center; }
    .window-inner .flex.flex-col { align-items: center; }
    .window-inner .flex:not(.flex-col) { justify-content: center; }
    .window-inner :is(.items-start, .text-left) { align-items: center; text-align: center !important; }
    .window-inner :is(.self-end, .mx-auto, .ml-auto, .mr-auto) { align-self: center !important; }

    /* Dragging/resizing/min/max don't apply on a phone. */
    .window-frame .resizer { display: none; }
    .win-ctrl-min, .win-ctrl-max { display: none; }

    /* Maximize falls back to the same full-screen sheet bounds. */
    .maximized {
        top: calc(3rem + env(safe-area-inset-top)) !important;
        left: 0.5rem !important;
        width: calc(100vw - 1rem) !important;
        height: calc(100dvh - 3rem - 6rem - env(safe-area-inset-top) - env(safe-area-inset-bottom)) !important;
    }
}

/* ============================================================
   SHORT PHONES (iPhone SE class, <=700px tall). The regular
   phone scale above still overflows the ~475px sheet, so app
   content scrolled and clipped. Reclaim the sheet's top margin
   and shrink the few tall blocks (hero art, form fields, card
   padding) until every app fits its sheet without scrolling.
   Type sizes stay at the readable phone scale; buttons and
   inputs keep finger-sized hit areas.
   ============================================================ */
@media (max-width: 767px) and (max-height: 700px) {
    /* Taller sheet: reclaim the regular phone tier's 3rem top clearance. */
    .window-frame, .maximized {
        top: calc(0.75rem + env(safe-area-inset-top)) !important;
        height: calc(100dvh - 0.75rem - 6rem - env(safe-area-inset-top) - env(safe-area-inset-bottom)) !important;
    }

    /* Tighter outer padding and vertical rhythm. */
    .window-inner .p-8 { padding: 0.85rem !important; }
    .window-inner .pt-20 { padding-top: 0.85rem !important; }
    .window-inner .p-6 { padding: 0.75rem !important; }
    .window-inner .p-5 { padding: 0.75rem !important; }
    .window-inner .py-6 { padding-top: 0.5rem !important; padding-bottom: 0.5rem !important; }
    .window-inner .mt-16 { margin-top: 0.6rem !important; }
    .window-inner :is(.mb-8, .mb-6, .mb-4) { margin-bottom: 0.5rem !important; }

    /* Hero/course art are the tallest blocks: cap them harder.
       (.text-left scopes to course cards so the Docs/Blog hero
       icons, which already fit, keep their size.) */
    .window-inner .w-44.h-44 { width: 5.5rem !important; height: 5.5rem !important; }
    .window-inner .text-left .w-28.h-28 { width: 5rem !important; height: 5rem !important; }

    /* Contact form: slimmer fields and a 3-line message box.
       ~10px input padding keeps a ~43px touch target. */
    .window-inner form .p-3 { padding: 0.625rem !important; }
    .window-inner form textarea { height: 5rem !important; }
}

/* ============================================================
   KNOWLEDGE BASE — phones
   Placed last so it overrides the generic mobile .window-inner
   rules above (which center text and were tuned for the other,
   card-style apps). The KnowledgeBase is text-heavy and needs left-aligned
   reading; the sidebar/TOC panes are dropped for a single column.
   ============================================================ */
@media (max-width: 767px) {
    .window-inner .kb,
    .window-inner .kb * { text-align: left; }
    .window-inner .kb .flex,
    .window-inner .kb .flex.flex-col { align-items: stretch; justify-content: flex-start; }

    .kb-landing { padding: 1.1rem 1.1rem 2rem; }
    .kb-hero h2 { font-size: 1.4rem !important; }
    .kb-cards { grid-template-columns: 1fr; }
    .kb-home { grid-template-columns: 1fr; }
    .kb-search { margin-bottom: 1.25rem; }
    /* Stack domain title over its blurb so titles don't wrap mid-phrase. */
    .kb-domain-head { flex-direction: column; align-items: flex-start; gap: 0.1rem; }

    /* Collapse the three-pane layout to a single content column. The TOC is
       dropped; the sidebar (switcher + tree) becomes an off-canvas drawer
       opened by the "☰ Sections" button. */
    .kb-article-view { display: block; }
    .kb-toc { display: none; }
    .kb-content { height: 100%; padding: 1.1rem 1.1rem 2rem; }
    .kb-doc { max-width: 100%; }
    .kb-doc h1 { font-size: 1.4rem !important; }
    .kb-doc h2 { font-size: 1.15rem !important; }
    .kb-doc h3 { font-size: 1.02rem !important; }

    /* Sections row: drawer toggle + back button, finger-sized. */
    .kb-content-top { display: flex; gap: 0.5rem; align-items: center; margin-bottom: 1rem; }
    .kb-nav-toggle {
        display: inline-flex; align-items: center; min-height: 44px;
        padding: 0.4rem 0.9rem; background: var(--accent-lime);
        border: var(--border-black); border-radius: 8px; box-shadow: 2px 2px 0 #000;
    }
    .kb-content-top .kb-back { margin-bottom: 0; min-height: 44px; display: inline-flex; align-items: center; }

    /* Off-canvas drawer. */
    .kb-sidebar {
        display: block; position: absolute; top: 0; bottom: 0; left: 0;
        width: 84%; max-width: 300px; z-index: 30;
        transform: translateX(-100%); transition: transform 0.25s ease;
    }
    .kb-article-view.nav-open .kb-sidebar { transform: translateX(0); box-shadow: 6px 0 0 rgba(0,0,0,0.12); }
    .kb-article-view.nav-open .kb-backdrop {
        display: block; position: absolute; inset: 0; z-index: 25; background: rgba(0,0,0,0.35);
    }
    /* Bigger touch targets inside the drawer. */
    .kb-row { padding-top: 0.5rem; padding-bottom: 0.5rem; }
    .kb-switcher-item { padding: 0.6rem; }

    /* Blog: single-column landing, drop the TOC in the reading view. */
    .blog-landing { padding: 1.1rem 1.1rem 2rem; }
    .blog-hero h2 { font-size: 1.4rem !important; }
    .blog-cards { grid-template-columns: 1fr; }
    .blog-search { margin-bottom: 1.25rem; }
    .blog-row { grid-template-columns: minmax(0, 1fr) auto; }
    .blog-row-date { grid-column: 1 / -1; }
    .blog-post-view { display: block; }
    .blog-post-view .kb-toc { display: none; }
    .blog-post-view .kb-content { height: 100%; padding: 1.1rem 1.1rem 2rem; }
    .blog-post-header h1 { font-size: 1.4rem !important; }
}
