/* Writing section styles — the infinite canvas of notes that lives inside
   #writing on the home page. Adapted from experiments/infinite-canvas/index.html
   with three structural changes:
     - All rules scoped to #writing so they don't leak to other sections.
     - .canvas fills the #writing container (position: absolute) rather than
       the viewport (position: fixed); same for the table-view.
     - The view-toggle and filter-chip strip live at the BOTTOM of the
       viewport (bottom-left and bottom-right) rather than the top, per the
       merge design — keeps the top edge clean and visually distinct from
       the canvas-internal nav.
   The cream/black/sage color tokens come from styles/variables.css (parent
   site's palette). The --ink/--muted/--card-bg/--card-border tokens are
   writing-specific and scoped inside the #writing block so they don't
   pollute the global namespace. */

#writing {
    /* Override the .container rule's defaults: it sets max-width and heavy
       padding for centered article-style content; the canvas needs to fill
       the section edge-to-edge. */
    padding: 0 !important;
    max-width: none !important;
    margin: 0 !important;
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
    /* main-content-area has pointer-events: none (so clicks pass to the viz
       layer); we re-enable here so the canvas can capture pan/zoom and the
       toggle/chip buttons are interactive. */
    pointer-events: auto;

    /* Writing-local palette extensions (the parent's variables.css covers
       --yellow, --black, --sage; these warmer in-between tones are unique
       to the canvas's paper-on-desk aesthetic). */
    --ink: #1a1a1a;
    --muted: #6a6147;
    --card-bg: #f4ecc7;
    --card-border: #8a7a48;
}

/* Off-screen measurement state — applied by writing-canvas.js around the
   prepare()'s measurement phase when the user is on a different section
   and #writing is otherwise display:none. The browser must include
   #writing in layout for measurement elements inside to have non-zero
   offsetHeight; this class forces it into the layout but moves it off-
   screen (position:fixed at left:-99999px) and makes it invisible
   (visibility:hidden), so the user never sees a flash. The class is
   removed as soon as measurement completes (or immediately if the user
   navigates to writing during the off-screen window). The !important
   markers are required because the section's inline style="display: none"
   would otherwise win the cascade. Width/height are explicit because
   position:fixed makes percentages relative to viewport, and we need
   the same effective size during measurement as when actually displayed
   so card text wraps the same way. */
#writing.writing-measuring {
    display: block !important;
    visibility: hidden !important;
    position: fixed !important;
    top: 0 !important;
    left: -99999px !important;
    width: 100vw !important;
    height: 100vh !important;
}

/* Canvas viewport — fills the full viewport (position: fixed, inset: 0)
   rather than just the #writing section, so cards can appear behind the
   transparent nav at the top, matching how the boids visualization on
   the home page extends to the top of the viewport. The nav is z-100
   and floats on top; the canvas is at the main-content-area stacking
   context (z-10) so it sits behind the nav but above body. No
   background-color, no background-image — the canvas is purely a
   transparent stage for the cards. Body's background-color (set by the
   theme-surfaces rule in base.css) provides the page color, shown
   through the transparent canvas and the transparent #writing wrapper. */
#writing .canvas {
    position: fixed;
    inset: 0;
    cursor: grab;
    overflow: hidden;
}
#writing .canvas.panning { cursor: grabbing; }

/* Canvas render surface — drawn into by JS via 2D context.
   position: absolute with inset: 0 fills the parent .canvas div.
   pointer-events: auto so it captures clicks / mousemove for hit-testing.
   z-index: 1 sits below the hover-overlay (z-index: 2) so the hover
   ring paints on top of the cards. */
#writing #canvas-render {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    pointer-events: auto;
    z-index: 1;
}

/* Hover overlay — a single DOM element positioned by JS over the hovered
   card's screen rect. pointer-events: none so it doesn't intercept the
   underlying canvas's events; the hover state is purely visual. The
   border-color and width can be edited here in CSS since the overlay is
   a real DOM element. */
#writing #hover-overlay {
    position: absolute;
    display: none;
    pointer-events: none;
    border: 2px solid var(--ink);
    box-sizing: border-box;
    z-index: 2;
}

/* Cards.
   In production, cards no longer exist as DOM elements — they're rasterized
   to bitmaps during prepare and composited to the #canvas-render element
   via the 2D drawing context. The rules below apply only briefly: during
   measurement (writing-canvas.js phase 1, to read offsetHeight) and during
   rasterization (phase 6, where modern-screenshot captures the styled card
   to an Image). Once both phases complete, no .card DOM nodes exist on
   the page. The hover state lives in #hover-overlay (a single DOM element
   positioned over the hovered card), not on these rules. */
#writing .card {
    position: absolute;
    background: var(--card-bg);
    border: 1px solid var(--card-border);
    padding: 12px 14px 14px;
    font-size: 12px;
    line-height: 1.45;
    color: var(--ink);
    overflow: hidden;
    /* Opt out of the site-wide text-shadow glow (defined in cursor-orb.css's
       `body { text-shadow: 0 0 5px ... }`). Cards inherit through CSS by
       default; setting `none` here propagates to all descendants of .card
       (title, snippet, dates, tags), so html2canvas captures sharp text
       during rasterization. The rest of the site keeps its glow. */
    text-shadow: none;
}
#writing .card-header {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 6px;
    font-size: 10px;
    color: var(--muted);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    gap: 8px;
}
#writing .card-date { white-space: nowrap; }
#writing .card-meta {
    display: flex; gap: 6px; align-items: baseline;
    flex-wrap: wrap; justify-content: flex-end;
}
#writing .card-badge {
    background: var(--sage);
    border: 1px solid rgba(0,0,0,0.2);
    padding: 1px 5px;
    font-size: 9px;
    letter-spacing: 0.04em;
    border-radius: 2px;
    color: #1a3a32;
}
#writing .card-badge.quoted { background: #e8d4a8; color: #5a4a1a; }
#writing .card-title {
    font-weight: 600;
    margin-bottom: 6px;
    font-size: 13px;
    line-height: 1.3;
}
#writing .card-snippet {
    color: var(--ink);
    opacity: 0.75;
    font-size: 11px;
    line-height: 1.5;
    white-space: pre-wrap;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
}

/* HUD overlays — kept fixed to viewport since they're loading/status indicators */
#writing .hud {
    position: fixed;
    z-index: 1000;
    font-size: 11px;
    letter-spacing: 0.04em;
    color: var(--ink);
    opacity: 0.7;
    pointer-events: none;
}
#writing .hud-loading {
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    font-size: 13px;
    opacity: 0.8;
}

/* View toggle — BOTTOM-left now (was top-left in standalone). Single
   segmented pill matching fleetingbits-io's nav-link vocabulary: 2px solid
   black outline, fully rounded pill, IBM Plex Mono. The two halves invert:
   active half is filled black with page-cream text (like a nav-link at rest),
   inactive half is page-cream with black text (like a nav-link on hover). */
#writing .view-toggle {
    position: fixed;
    bottom: 14px;
    left: 22px;
    z-index: 1500;
    display: inline-flex;
    background: transparent;
    border: 2px solid var(--black);
    border-radius: 16px;
    overflow: hidden;
}
#writing .view-toggle button {
    font-family: inherit;
    font-size: 13px;
    font-weight: 500;
    background: var(--yellow);
    border: none;
    outline: none;
    color: var(--black);
    padding: 6px 18px;
    cursor: pointer;
    text-transform: lowercase;
    letter-spacing: 0.05em;
    line-height: 1.3;
    transition: background-color 200ms ease-out, color 200ms ease-out;
}
#writing .view-toggle button + button {
    border-left: 2px solid var(--black);
}
#writing .view-toggle button:not(.active):hover,
#writing .view-toggle button:not(.active):focus-visible {
    background: var(--black);
    color: var(--yellow);
}
#writing .view-toggle button.active {
    background: var(--black);
    color: var(--yellow);
    font-weight: 600;
}

/* View-visibility: hide the inactive view via opacity + pointer-events
   instead of display:none. Both views stay in the rendering pipeline so
   toggling is a fast opacity flip rather than a full DOM teardown. This
   also keeps the table's <thead> in layout so it participates in the
   cats→writing color fade (its background-color is in the theme-surfaces
   rule in base.css). */
body.view-canvas #writing .table-view,
body.view-table #writing .canvas {
    opacity: 0;
    pointer-events: none;
}

/* Canvas mode: skip rendering the table's body rows so the document
   doesn't grow ~7,500px and trigger Safari's phantom scrollbar.
   content-visibility:hidden (vs display:none) caches the rows' render
   state, so toggling back to table view reuses the cached layout pass
   instead of rebuilding it from scratch. The thead is unaffected — it
   sits outside the tbody and remains in layout for the theme fade. */
body.view-canvas #writing .table-view tbody {
    content-visibility: hidden;
}

/* Table view — fills #writing leaving 60px at the BOTTOM for the toggle/chip
   strip (was inset 60px from the top in standalone). background-color comes
   from the theme-surfaces rule in base.css so the table fades with the
   page theme during a cats→writing transition. */
#writing .table-view {
    position: absolute;
    /* Bottom inset of 80px (was 60px) creates ~33px of cream between the
       table's clip line and the top of the floating view-toggle, so the
       toggle reads as a distinct floating control rather than jammed
       against the last visible row. The toggle stays at its own bottom: 14px;
       only the table's clip line moves. */
    inset: 0 0 80px 0;
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

/* Active filter chips — BOTTOM-right now (was top-right in standalone),
   mirroring the view-toggle at bottom-left. Appear only when filters
   exist; an empty container occupies no visual space. */
#writing .table-filters {
    position: fixed;
    bottom: 14px;
    right: 22px;
    z-index: 1500;
    display: flex;
    flex-wrap: wrap;
    justify-content: flex-end;
    gap: 6px;
    max-width: calc(100vw - 240px);
}

/* Active filter chip — already-applied tag. Strong "active" appearance
   (black fill, cream text, 2px black border). The × close button fades up
   on hover to signal it's the removal target. */
#writing .table-filter-chip {
    display: inline-flex;
    align-items: center;
    background: var(--black);
    color: var(--yellow);
    border: 2px solid var(--black);
    padding: 3px 4px 3px 12px;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: lowercase;
    border-radius: 14px;
}
#writing .table-filter-chip button {
    background: none;
    border: none;
    outline: none;
    color: inherit;
    cursor: pointer;
    font-family: inherit;
    font-size: 14px;
    line-height: 1;
    padding: 0 6px;
    opacity: 0.7;
    transition: opacity 200ms ease-out;
}
#writing .table-filter-chip button:hover,
#writing .table-filter-chip button:focus-visible {
    opacity: 1;
}
#writing .table-scroll {
    flex: 1;
    overflow-y: auto;
    padding: 0 24px 40px;
}
#writing .table-view table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
}
/* Sticky table header — needs its own background so scrolling rows
   don't bleed through. background-color comes from theme-surfaces in
   base.css, matching the table-view it sits on top of. */
#writing .table-view thead th {
    position: sticky;
    top: 0;
    text-align: left;
    padding: 10px 8px;
    border-bottom: 1px solid rgba(0,0,0,0.25);
    font-weight: 600;
    text-transform: lowercase;
    letter-spacing: 0.06em;
    font-size: 14px;
    color: var(--ink);
    z-index: 1;
}
#writing .table-view thead th.th-sortable {
    cursor: pointer;
    user-select: none;
}
#writing .table-view thead th.th-num { text-align: right; }
#writing .table-view thead th.sort-asc::after  { content: ' ↑'; opacity: 0.7; }
#writing .table-view thead th.sort-desc::after { content: ' ↓'; opacity: 0.7; }

#writing .table-view tbody tr {
    cursor: pointer;
    border-bottom: 1px solid rgba(0,0,0,0.07);
}
#writing .table-view tbody tr:hover { background: rgba(0,0,0,0.04); }
#writing .table-view tbody td {
    padding: 8px;
    vertical-align: top;
    line-height: 1.4;
}
#writing .table-view td.td-date {
    white-space: nowrap;
    color: var(--ink);
    font-size: 14px;
    width: 110px;
}
/* All four columns share --ink as text color; hierarchy comes from content
   (title is the only sentence-length cell), not from color/weight split. */
#writing .table-view td.td-title { color: var(--ink); }
#writing .table-view td.td-tags {
    width: 40%;
    max-width: 0; /* let flex children inside actually wrap */
}
#writing .table-view td.td-tags-inner {
    display: flex;
    flex-wrap: wrap;
    gap: 2px 10px;
    /* Compensates for .row-tag's 9px left padding so the first tag's
       text aligns with the "tags" column header instead of sitting 9px
       inboard. The hover pill on the first tag extends 1px past the
       cell's left edge, which is invisible (no cell borders, soft rgba). */
    margin-left: -9px;
}
#writing .table-view td.td-length {
    text-align: right;
    color: var(--ink);
    font-size: 14px;
    width: 60px;
    white-space: nowrap;
}
/* In-row tag pill — inline metadata at rest, soft pill on hover. */
#writing .row-tag {
    display: inline-block;
    background: transparent;
    color: var(--ink);
    padding: 2px 9px;
    font-size: 14px;
    letter-spacing: 0.04em;
    text-transform: lowercase;
    border-radius: 11px;
    cursor: pointer;
    line-height: 1.3;
    transition: background-color 200ms ease-out;
}
#writing .row-tag:hover,
#writing .row-tag:focus-visible {
    background: rgba(0, 0, 0, 0.08);
    outline: none;
}

/* Note window (retro-window pattern) — content area styling for notes
   opened from the canvas or table. The window chrome (header, drag,
   close, resize) comes from styles/retro-window.css; these rules style
   only the article inside the .retro-window-content area. */
#note-window .note-article {
    user-select: text;
    -webkit-user-select: text;
    max-width: 70ch;
    margin: 0 auto;
}
#note-window .note-meta {
    font-size: 11px;
    color: var(--muted, #6a6147);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 10px;
}
#note-window .note-article h3 {
    font-size: 18px !important;
    font-weight: 600 !important;
    line-height: 1.3 !important;
    margin-bottom: 14px;
}
#note-window .note-body {
    white-space: pre-wrap;
    font-size: 14px;
    line-height: 1.65;
    color: var(--ink, #1a1a1a);
}
#note-window .note-links {
    margin-top: 22px;
    padding-top: 14px;
    border-top: 1px solid rgba(0,0,0,0.15);
    font-size: 11px;
    color: var(--muted, #6a6147);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
#note-window .note-links a {
    color: var(--ink, #1a1a1a);
    text-decoration: none;
    border-bottom: 1px dotted currentColor;
    display: inline-block;
    margin: 2px 8px 2px 0;
    text-transform: none;
    letter-spacing: 0;
}

/* When on the writing section, hide the music toggle so the bottom-right
   is free for the filter chips. Mirrors how cats theme hides music. */
body[data-section="writing"] .music-toggle {
    display: none;
}

/* Mobile writing list — each row is a trigger that grows a full-screen reader
   out of itself (mobile-swipe.js builds the list from numbered_lists/notes.json
   and creates the .mobile-reader overlay). */
.mobile-writing-list {
    list-style: none;
    margin: 0;
    padding: 0;
}
.mobile-writing-row {
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}
.mobile-writing-link {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 100%;
    margin: 0;
    padding: 12px 20px;
    border: none;
    background: transparent;
    text-align: left;
    font: inherit;
    color: inherit;
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
    transition: background-color 120ms ease, transform 120ms ease;
}
.mobile-writing-link:active {
    background: rgba(0, 0, 0, 0.05);
    transform: scale(0.99); /* subtle tactile press on tap */
}
.mobile-writing-date {
    font-size: 11px;
    color: #6a6147;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.mobile-writing-title {
    font-size: 15px;
    line-height: 1.35;
    color: #1a1a1a;
}

/* Full-screen reader that grows out of the tapped row (container transform).
   The white box scales from the row's rect to full-screen while the content
   fades in (.animating), so the scale never shows as text distortion. */
.mobile-reader {
    position: fixed;
    inset: 0;
    z-index: 200;
    background: #FFFFFF;
    display: none;
    will-change: transform;
    transition: transform 300ms cubic-bezier(0.2, 0.8, 0.2, 1),
                opacity 260ms ease;
}
.mobile-reader.open {
    display: block;
}
.mobile-reader-content {
    display: flex;
    flex-direction: column;
    height: 100%;
}
.mobile-reader-scroll {
    flex: 1 1 auto;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
}
.mobile-reader-inner {
    max-width: 640px;
    margin: 0 auto;
    /* top clears the status bar / notch (previously handled by the removed top
       bar); bottom leaves room so the FAB never covers content. */
    padding: max(16px, env(safe-area-inset-top, 0px)) 22px 96px 22px;
}
.mobile-reader-title {
    font-size: 22px;
    line-height: 1.25;
    font-weight: 600;
    color: #1a1a1a;
    margin: 0 0 6px 0;
    text-align: left; /* override the global mobile `h1 { text-align: center }` */
}
.mobile-reader-meta {
    font-size: 11px;
    color: #6a6147;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-bottom: 22px;
}
.mobile-reader-body {
    font-size: 16px;
    line-height: 1.62;
    color: #1a1a1a;
    white-space: pre-wrap;        /* preserve the note's paragraph breaks */
    overflow-wrap: anywhere;
}
.mobile-reader-links {
    margin-top: 30px;
    border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.mobile-reader-linkrow {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 15px 2px;
    border-bottom: 1px solid rgba(0, 0, 0, 0.08);
    color: #3a6ea5;
    text-decoration: none;
    font-size: 15px;
    overflow-wrap: anywhere;
}
.mobile-reader-linkarrow {
    color: #a59b7d;
    flex: 0 0 auto;
}

/* Floating back/dismiss button — bottom-right so it falls under a right
   thumb. Lives inside the reader so it slides with it and only shows while
   reading. */
.mobile-reader-fab {
    position: absolute;
    right: max(18px, env(safe-area-inset-right, 0px));
    bottom: max(22px, env(safe-area-inset-bottom, 0px));
    width: 52px;
    height: 52px;
    border-radius: 50%;
    border: none;
    background: #1a1a1a;
    color: #FFFFFF;
    font-size: 19px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.28);
    cursor: pointer;
    z-index: 3;
    -webkit-tap-highlight-color: transparent;
    transition: transform 120ms ease;
}
.mobile-reader-fab:active {
    transform: scale(0.92);
}
