@import "tailwindcss"; /* * SALON HANG — gallery theme. * Aged parchment ground, oxblood ink, ochre+cobalt+vermillion accents. * Romantic gravity (Friedrich, Dix, Goya) + raw scrawl (Basquiat) + bold cutout (Matisse, Kahlo). */ @theme { --color-crust: var(--crust); --color-mantle: var(--mantle); --color-bg: var(--base); --color-surface0: var(--surface0); --color-surface1: var(--surface1); --color-surface2: var(--surface2); --color-overlay0: var(--overlay0); --color-overlay1: var(--overlay1); --color-overlay2: var(--overlay2); --color-text: var(--text); --color-subtext0: var(--subtext0); --color-subtext1: var(--subtext1); --color-blue: var(--blue); --color-lavender: var(--lavender); --color-sapphire: var(--sapphire); --color-sky: var(--sky); --color-teal: var(--teal); --color-green: var(--green); --color-yellow: var(--yellow); --color-peach: var(--peach); --color-maroon: var(--maroon); --color-red: var(--red); --color-mauve: var(--mauve); --color-pink: var(--pink); --color-flamingo: var(--flamingo); --color-rosewater: var(--rosewater); --font-sans: 'EB Garamond Variable', 'EB Garamond', Georgia, 'Times New Roman', serif; --font-display: 'Fraunces Variable', 'Fraunces', Georgia, 'Times New Roman', serif; --font-hand: 'Caveat', 'Bradley Hand', cursive; --font-mono: 'JetBrains Mono Variable', ui-monospace, 'SF Mono', Menlo, monospace; } /* SALON — default. Aged parchment with romantic weight. */ :root, .salon { --crust: #14100C; --mantle: #2A1F18; --base: #ECE0C6; --surface0: #DDCEB0; --surface1: #B69C70; --surface2: #826846; --overlay0: #5C463A; --overlay1: #463226; --overlay2: #2E1F17; --text: #1A120C; --subtext0: #5C463A; --subtext1: #3D2B1E; /* accents — mapped to the original token names so existing UI flows pick them up */ --blue: #1F3A78; /* Kahlo cobalt */ --lavender: #5C4D7A; /* faded violet */ --sapphire: #2B3E5C; /* deep ink-blue */ --sky: #4A6FA0; /* muted azure */ --teal: #4C7264; /* verdigris */ --green: #6A7341; /* olive */ --yellow: #C9882B; /* Friedrich ochre */ --peach: #C26847; /* terracotta */ --maroon: #6B2B2A; /* wine */ --red: #B83A2B; /* Matisse/Goya vermillion */ --mauve: #6B1F1A; /* oxblood — primary accent */ --pink: #B85A6C; /* rosehip */ --flamingo: #C77A6C; /* faded coral */ --rosewater: #E8D9BD; /* bone */ } /* Salon Noir — black gallery wall variant (Goya black paintings, Abramović stark). */ .salon-noir { --crust: #050402; --mantle: #0E0A06; --base: #16110B; --surface0: #221A12; --surface1: #3A2B1E; --surface2: #5C4530; --overlay0: #7A5D43; --overlay1: #93755A; --overlay2: #B69779; --text: #ECE0C6; --subtext0: #B69C70; --subtext1: #D6C49E; --blue: #5A7DC4; --lavender: #9A8DBE; --sapphire: #87A9D8; --sky: #B0C4E0; --teal: #84A89A; --green: #B9C076; --yellow: #E9B854; --peach: #E89570; --maroon: #A04A47; --red: #E25940; --mauve: #C24336; /* lifted oxblood for dark bg contrast */ --pink: #E090A0; --flamingo: #EBA797; --rosewater: #F4E5C9; } /* BREAKCORE — early-2000s web rot + breakcore. CRT-violet ground, hot * magenta primary, acid green / electric cyan / hazard yellow accents. * Glitchy, blown-out, MSN-era saturation. */ .breakcore { --crust: #02000A; --mantle: #06031A; --base: #0A0612; --surface0: #150929; --surface1: #22113F; --surface2: #3A1B62; --overlay0: #5A2D8E; --overlay1: #7B45B8; --overlay2: #A06AD8; --text: #F2F0FF; --subtext0: #B9A8E0; --subtext1: #D8CCFA; --blue: #00B7FF; /* MSN cyan */ --lavender: #B98CFF; /* CRT violet */ --sapphire: #4B6BFF; /* hyperlink */ --sky: #66E1FF; /* aqua chrome */ --teal: #00F5C8; /* matrix mint */ --green: #B6FF00; /* acid */ --yellow: #FFD400; /* hazard */ --peach: #FF8A3D; /* GIF-era flame */ --maroon: #8B0A4B; --red: #FF1F4F; /* siren */ --mauve: #FF2EA6; /* hot magenta — primary accent */ --pink: #FF7AD8; /* bubblegum */ --flamingo: #FFA2C4; --rosewater: #FFE8F6; } /* GOTHIC — cathedral nightfall. Midnight violet ground, blood crimson, * tarnished candle gold, stained-glass indigo. Catholic-gothic + Sisters of * Mercy + Bauhaus stark. Primary accent: cathedral velvet mauve. */ .gothic { --crust: #030104; --mantle: #0A0710; --base: #110B18; --surface0: #1A1224; --surface1: #261A36; --surface2: #382550; --overlay0: #4F3970; --overlay1: #6E5293; --overlay2: #8D72B1; --text: #EDE3F2; /* bone, violet wash */ --subtext0: #9B8AB0; --subtext1: #C0AED2; --blue: #4239A4; /* stained-glass deep */ --lavender: #9B7BD4; /* candlelight through purple glass */ --sapphire: #5947B2; --sky: #7C68C9; --teal: #487B8A; /* verdigris on bronze */ --green: #5E7842; /* cemetery moss */ --yellow: #D4A82B; /* taper / tarnished brass */ --peach: #B45A38; /* rust */ --maroon: #5B1A24; --red: #A41827; /* arterial */ --mauve: #8B2C9E; /* cathedral velvet — primary accent */ --pink: #B25288; /* dried rose */ --flamingo: #C57B96; --rosewater: #F0DDE8; } /* CYBERSIGIL — Frostbite. Near-black ground, ice-cyan sigil linework, * bruised-magenta primary accent, sterile bone-white text. Modern-breakcore * melancholy: chromatic-aberration glitch, barbed sigil ornament, deep * vignette + fine cold grain. Primary accent: bruised magenta (--mauve). */ .cybersigil { --crust: #020203; --mantle: #050507; --base: #070709; --surface0: #0C0D11; --surface1: #13151B; --surface2: #1E2129; --overlay0: #2A2F3A; --overlay1: #3D4654; --overlay2: #566174; --text: #DCE6EC; /* sterile bone-white, cool cast */ --subtext0: #7E8B99; --subtext1: #AAB8C4; --blue: #3FB4FF; /* cold electric */ --lavender: #8E7CFF; /* cold violet */ --sapphire: #3A5BFF; /* deep cold hyperlink */ --sky: #4FE9FF; /* ice-cyan — primary sigil line */ --teal: #2FD8D2; /* frost mint — secondary neon */ --green: #5BE0A8; /* cold jade */ --yellow: #E8C24A; /* muted amber — inline code only */ --peach: #E07A5F; --maroon: #5A1530; --red: #FF3B5C; /* siren — danger only */ --mauve: #C8327A; /* bruised magenta — primary accent */ --pink: #E86AAE; /* faded neon pink */ --flamingo: #E8A0C4; --rosewater: #EAF2F6; /* brightest bone — on-accent text */ } html { font-family: var(--font-sans); font-feature-settings: "kern", "liga", "calt", "onum"; } body { background-color: var(--base); color: var(--text); min-height: 100vh; transition: background-color 0.3s ease, color 0.3s ease; -webkit-font-smoothing: antialiased; font-size: 1.0625rem; line-height: 1.65; position: relative; } /* Paper grain — applied as a fixed overlay so every page gets the texture. * All three layers sit behind content (negative z-index) so fixed-positioned * modals (e.g. the search palette) can escape ancestor stacking traps. */ body::before { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: -3; background-color: var(--base); } body::after { content: ""; position: fixed; inset: 0; pointer-events: none; z-index: -1; opacity: 0.32; mix-blend-mode: multiply; background-image: url("data:image/svg+xml;utf8,"); } .salon-noir body::after, html.salon-noir body::after { opacity: 0.5; } .gothic body::after, html.gothic body::after { opacity: 0.55; background-image: url("data:image/svg+xml;utf8,"); mix-blend-mode: screen; } /* Breakcore: blown-out RGB-tinted digital noise + CRT scanlines. */ .breakcore body::after, html.breakcore body::after { opacity: 0.55; background-image: url("data:image/svg+xml;utf8,"), repeating-linear-gradient( 0deg, rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) 2px, rgba(0, 0, 0, 0.28) 3px, rgba(0, 0, 0, 0) 4px ); mix-blend-mode: screen; } .breakcore .salon-atmosphere::before { opacity: 0.32; } .breakcore .salon-atmosphere::after { opacity: 0.28; } /* Floating motes of pigment — far background, very subtle. */ .salon-atmosphere { position: fixed; inset: 0; z-index: -2; pointer-events: none; overflow: hidden; } .salon-atmosphere::before, .salon-atmosphere::after { content: ""; position: absolute; border-radius: 50%; filter: blur(120px); opacity: 0.18; } .salon-atmosphere::before { width: 55vw; height: 55vw; top: -15vw; left: -10vw; background: var(--mauve); } .salon-atmosphere::after { width: 45vw; height: 45vw; bottom: -10vw; right: -10vw; background: var(--blue); opacity: 0.12; } code, pre, kbd, samp { font-family: var(--font-mono); } /* Selection */ ::selection { background: var(--mauve); color: var(--rosewater); } /* Breakcore: chromatic-aberration glow on display headings + nameplate. */ .breakcore .prose h1, .breakcore .prose h2, .breakcore h1.font-display, .breakcore .nameplate-title { text-shadow: -1px 0 0 color-mix(in srgb, var(--teal) 70%, transparent), 1px 0 0 color-mix(in srgb, var(--mauve) 70%, transparent), 0 0 18px color-mix(in srgb, var(--mauve) 35%, transparent); } .breakcore ::selection { background: var(--green); color: var(--crust); text-shadow: 0 0 6px var(--mauve); } /* ───── Display utilities ───── */ .font-display { font-family: var(--font-display); font-feature-settings: "kern", "liga", "calt", "lnum", "ss01"; letter-spacing: -0.01em; } .font-hand { font-family: var(--font-hand); font-weight: 400; } .font-display-italic { font-family: var(--font-display); font-style: italic; font-feature-settings: "kern", "liga", "calt", "ss01"; } /* Roman numerals get small-caps treatment */ .numeral { font-family: var(--font-display); font-variant-numeric: lining-nums; letter-spacing: 0.08em; font-weight: 500; } /* ───── Salon prose — exhibit plaque body ───── */ .prose { color: var(--text); max-width: none; line-height: 1.75; font-size: 1.125rem; font-family: var(--font-sans); } @media (min-width: 768px) { .prose { font-size: 1.1875rem; } } .prose > *:first-child { margin-top: 0; } .prose h1 { font-family: var(--font-display); font-size: clamp(2rem, 1.5rem + 2vw, 3rem); font-weight: 600; font-style: italic; color: var(--text); margin: 0 0 1.25rem; line-height: 1.15; letter-spacing: -0.02em; padding-bottom: 0.06em; } .prose h2 { font-family: var(--font-display); font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem); font-weight: 500; color: var(--text); margin: 3rem 0 1rem; padding-bottom: 0.35rem; line-height: 1.2; letter-spacing: -0.01em; border-bottom: 1px solid color-mix(in srgb, var(--mauve) 30%, transparent); } .prose h3 { font-family: var(--font-display); font-size: 1.4rem; font-weight: 500; font-style: italic; color: var(--text); margin: 2.25rem 0 0.75rem; } .prose h4 { font-family: var(--font-display); font-size: 1.2rem; font-weight: 500; color: var(--subtext1); margin: 1.75rem 0 0.5rem; } .prose h5 { font-size: 0.85rem; font-weight: 600; color: var(--subtext0); text-transform: uppercase; letter-spacing: 0.18em; margin: 1.5rem 0 0.5rem; } .prose h6 { font-size: 0.85rem; font-weight: 500; color: var(--overlay0); font-style: italic; margin: 1rem 0 0.5rem; } .prose :is(h1, h2, h3, h4, h5, h6) { scroll-margin-top: 5rem; } .prose p { margin: 0 0 1.15rem; } .prose blockquote { border-left: 3px solid var(--mauve); padding: 0.25rem 0 0.25rem 1.4rem; margin: 1.75rem 0; color: var(--subtext1); font-style: italic; } .prose blockquote p { margin: 0 0 0.6rem; } .prose blockquote p:last-child { margin: 0; } .prose pre { padding: 1rem 1.1rem; border-radius: 0; border: 1px solid var(--surface2); border-left-width: 3px; border-left-color: var(--mauve); margin: 1.75rem 0; background-color: color-mix(in srgb, var(--surface0) 70%, transparent); font-size: 0.875rem; line-height: 1.55; overflow-x: auto; } .prose code { background-color: color-mix(in srgb, var(--surface0) 90%, transparent); padding: 0.1rem 0.4rem; border-radius: 0; border-bottom: 1px solid var(--surface1); font-size: 0.9em; color: var(--mauve); } .prose pre code { background: transparent; padding: 0; border: 0; color: inherit; font-size: inherit; } .prose a code, .prose :is(h1, h2, h3, h4) code { color: inherit; } .prose a { color: var(--mauve); text-decoration: underline; text-decoration-color: var(--surface1); text-decoration-thickness: 1px; text-underline-offset: 3px; transition: color 0.15s, text-decoration-color 0.15s; } .prose a:hover { color: var(--red); text-decoration-color: var(--red); } .prose ul, .prose ol { margin: 0 0 1.15rem; padding-left: 1.6rem; } .prose ul { list-style: none; } .prose ul > li { position: relative; padding-left: 0.2rem; } .prose ul > li::before { content: ""; position: absolute; left: -1.1rem; top: 0.62em; width: 0.42em; height: 0.42em; background: var(--mauve); transform: rotate(45deg); } .prose ol { list-style: decimal-leading-zero; } .prose ol > li::marker { color: var(--mauve); font-family: var(--font-display); font-style: italic; } .prose li { margin: 0.3rem 0; } /* Loose lists wrap items in

; drop the paragraph block-margin inside li. */ .prose li > p { margin: 0; } .prose li > p + p { margin-top: 0.6rem; } /* GFM task lists — kill the diamond, keep the checkbox. */ .prose ul > li:has(input[type="checkbox"]) { padding-left: 0; } .prose ul > li:has(input[type="checkbox"])::before { content: none; } .prose li > input[type="checkbox"] { margin: 0 0.5rem 0 0; vertical-align: 0.04em; accent-color: var(--mauve); } .prose hr { margin: 3rem auto; border: 0; height: 1px; width: 100%; background: linear-gradient( 90deg, transparent 0%, color-mix(in srgb, var(--mauve) 55%, transparent) 22%, transparent 45%, transparent 55%, color-mix(in srgb, var(--mauve) 55%, transparent) 78%, transparent 100% ); position: relative; overflow: visible; } .prose hr::before { content: ""; position: absolute; top: 50%; left: 50%; width: 0.5rem; height: 0.5rem; transform: translate(-50%, -50%) rotate(45deg); background: var(--mauve); } .prose strong { color: inherit; font-weight: 700; } .prose em { color: inherit; font-style: italic; font-family: var(--font-display); } .prose del { color: var(--overlay0); text-decoration: line-through; } /* ───── Figure / image plate — the heart of the gallery body ───── */ .prose figure { display: block; text-align: center; margin: 2.5rem 0; } .prose figure img, .prose img { display: block; max-width: 100%; height: auto; margin: 0 auto; border: 1px solid var(--surface2); padding: 6px; background: linear-gradient(var(--rosewater), var(--rosewater)) padding-box, linear-gradient(135deg, var(--surface2), var(--surface1)) border-box; box-shadow: 0 1px 0 var(--surface0), 0 18px 38px -22px rgba(20, 16, 12, 0.45), 0 2px 6px -2px rgba(20, 16, 12, 0.2); border-radius: 2px; } .salon-noir .prose figure img, .salon-noir .prose img, .gothic .prose figure img, .gothic .prose img, .breakcore .prose figure img, .breakcore .prose img { background: linear-gradient(var(--surface0), var(--surface0)) padding-box, linear-gradient(135deg, var(--surface2), var(--surface1)) border-box; box-shadow: 0 18px 38px -22px rgba(0, 0, 0, 0.7), 0 2px 6px -2px rgba(0, 0, 0, 0.5); } .gothic .prose figure img, .gothic .prose img { box-shadow: 0 18px 38px -22px rgba(0, 0, 0, 0.85), 0 2px 6px -2px rgba(0, 0, 0, 0.6), 0 0 0 1px color-mix(in srgb, var(--mauve) 22%, transparent); } .prose figure figcaption { font-family: var(--font-display); font-style: italic; font-size: 0.9rem; color: var(--subtext0); margin-top: 0.85rem; letter-spacing: 0.02em; line-height: 1.4; } /* Multi-image rows. Consecutive markdown images auto-collapse into a flex * row; each figure gets `flex: ` inline so widths divide * proportionally and heights line up. Wraps to a column on narrow screens. */ .prose .figure-row { /* Target row height. Each figure's flex-basis is ratio × this value, so * rows pack as many figures as fit at roughly --row-h tall, then wrap. * --row-max caps how tall a sparsely-filled final row can grow. */ --row-h: 16rem; --row-max: 30rem; display: flex; flex-wrap: wrap; gap: 0.9rem; align-items: flex-start; margin: 2.5rem 0; width: 100%; } @media (min-width: 1024px) { .prose .figure-row { --row-h: 18rem; --row-max: 34rem; } } .prose .figure-row figure { margin: 0; min-width: 0; /* allow flex children to shrink below content width */ flex-basis: 0; } .prose .figure-row figure img { width: 100%; max-width: 100%; height: auto; margin: 0; } .prose .figure-row figure figcaption { text-align: left; margin-top: 0.55rem; font-size: 0.82rem; } @media (max-width: 640px) { .prose .figure-row { flex-direction: column; width: 100%; margin-left: 0; gap: 1.4rem; } .prose .figure-row figure { flex: 1 1 100% !important; } .prose .figure-row figure figcaption { text-align: center; } } .prose figure figcaption::before { content: "— "; color: var(--mauve); } /* GFM tables — keep, slightly more editorial */ .prose table { display: block; width: 100%; max-width: 100%; overflow-x: auto; margin: 1.75rem 0; border-collapse: collapse; border: 1px solid var(--surface2); font-size: 0.95rem; font-family: var(--font-sans); } .prose thead { background-color: color-mix(in srgb, var(--surface0) 80%, transparent); } .prose th { padding: 0.55rem 0.9rem; text-align: left; font-weight: 600; color: var(--text); border-bottom: 1px solid var(--surface2); text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.75rem; } .prose td { padding: 0.5rem 0.9rem; border-bottom: 1px solid color-mix(in srgb, var(--surface1) 60%, transparent); } .prose tr:last-child td { border-bottom: 0; } /* ───── Salon plate — a single framed image card used on the gallery index ───── */ .plate { position: relative; background: var(--rosewater); padding: 14px 14px 0 14px; border: 1px solid var(--surface2); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--surface1) 50%, transparent), 0 1px 0 var(--surface0), 0 22px 42px -28px rgba(20, 16, 12, 0.5), 0 4px 12px -6px rgba(20, 16, 12, 0.25); border-radius: 2px; transition: transform 0.4s cubic-bezier(0.2, 0.6, 0.2, 1), box-shadow 0.4s cubic-bezier(0.2, 0.6, 0.2, 1); } .salon-noir .plate, .gothic .plate, .breakcore .plate { background: var(--surface0); } .salon-noir .plate, .gothic .plate { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--surface1) 50%, transparent), 0 22px 42px -28px rgba(0, 0, 0, 0.7), 0 4px 12px -6px rgba(0, 0, 0, 0.45); } .breakcore .plate { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mauve) 35%, transparent), 0 0 0 1px color-mix(in srgb, var(--mauve) 20%, transparent), 0 22px 42px -28px rgba(255, 46, 166, 0.35), 0 0 24px -8px color-mix(in srgb, var(--mauve) 40%, transparent); } .plate:hover { transform: translateY(-4px) rotate(-0.25deg); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--surface1) 60%, transparent), 0 1px 0 var(--surface0), 0 32px 60px -28px rgba(20, 16, 12, 0.55), 0 8px 20px -8px rgba(20, 16, 12, 0.3); } .salon-noir .plate:hover, .gothic .plate:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--surface1) 60%, transparent), 0 32px 60px -28px rgba(0, 0, 0, 0.8), 0 8px 20px -8px rgba(0, 0, 0, 0.55); } .breakcore .plate:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mauve) 45%, transparent), 0 0 0 1px color-mix(in srgb, var(--mauve) 30%, transparent), 0 32px 60px -28px rgba(255, 46, 166, 0.45), 0 0 32px -8px color-mix(in srgb, var(--mauve) 50%, transparent); } /* Keyboard focus for the card link — salon-appropriate inset frame + ring. */ .plate:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--mauve), 0 0 0 3px color-mix(in srgb, var(--mauve) 40%, transparent), 0 22px 42px -28px rgba(20, 16, 12, 0.5); } .breakcore .plate:focus-visible { box-shadow: inset 0 0 0 2px var(--mauve), 0 0 0 2px var(--green), 0 0 28px -6px color-mix(in srgb, var(--mauve) 60%, transparent); } .plate .plate-image { position: relative; overflow: hidden; background: var(--mantle); } .plate .plate-image img { display: block; width: 100%; height: 100%; object-fit: cover; filter: saturate(0.94) contrast(1.02); transition: transform 0.8s cubic-bezier(0.2, 0.6, 0.2, 1), filter 0.4s ease; } /* Natural mode — container drops fixed aspect so image shows its true ratio. */ .plate .plate-image.is-natural { height: auto; } .plate .plate-image.is-natural img { height: auto; object-fit: contain; } .plate:hover .plate-image img { transform: scale(1.03); filter: saturate(1.05) contrast(1.04); } .plate .plate-caption { padding: 14px 6px 16px 6px; margin-top: 2px; border-top: 1px solid color-mix(in srgb, var(--surface2) 50%, transparent); display: flex; flex-direction: column; gap: 0.4rem; } .plate .plate-caption-title { font-family: var(--font-display); font-style: italic; font-weight: 500; font-size: 1.18rem; line-height: 1.3; color: var(--text); letter-spacing: -0.005em; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; /* line-clamp's overflow:hidden clips italic-Fraunces descenders (g, y, p). * Pad the clip box and pull the layout back with a matching negative * margin so descenders survive without shifting siblings. */ padding-bottom: 0.16em; margin-bottom: -0.16em; transition: color 0.25s ease; } .plate:hover .plate-caption-title { color: var(--mauve); } .plate .plate-caption-summary { font-family: var(--font-sans); font-style: italic; font-size: 0.82rem; line-height: 1.45; color: var(--subtext0); display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; padding-bottom: 0.14em; margin-bottom: -0.14em; } .plate .plate-caption-meta { font-family: var(--font-sans); font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.22em; color: var(--subtext0); white-space: nowrap; display: flex; align-items: center; gap: 0.5rem; padding-top: 0.25rem; } .plate .plate-caption-sep { color: var(--mauve); opacity: 0.55; } .plate-tag-mini { position: absolute; bottom: 16px; right: 16px; background: color-mix(in srgb, var(--crust) 70%, transparent); color: var(--rosewater); border: 1px solid color-mix(in srgb, var(--rosewater) 18%, transparent); border-radius: 999px; font-family: var(--font-sans); font-size: 0.6rem; font-weight: 600; letter-spacing: 0.22em; padding: 4px 11px; text-transform: uppercase; backdrop-filter: blur(3px); } /* Breakcore: hard neon catalogue tag — sharp rect, offset shadow, glow. * Matches the layer's hazard-tape / hard-offset chrome language. */ .breakcore .plate-tag-mini { background: var(--crust); color: var(--green); border: 1px solid var(--mauve); border-radius: 0; font-family: var(--font-mono); font-weight: 500; letter-spacing: 0.14em; text-shadow: 0 0 6px color-mix(in srgb, var(--green) 60%, transparent); box-shadow: 2px 2px 0 var(--mauve), 0 0 14px -2px color-mix(in srgb, var(--mauve) 65%, transparent); backdrop-filter: none; } /* Nameplate — the museum-style header used in the site chrome */ .nameplate { display: inline-flex; flex-direction: column; align-items: flex-start; gap: 2px; position: relative; } .nameplate::after { content: ""; position: absolute; left: 0; right: 0; bottom: -6px; height: 2px; background: linear-gradient(to right, var(--mauve) 0%, var(--mauve) 35%, var(--surface2) 35%, var(--surface2) 100%); } .nameplate-title { font-family: var(--font-display); font-weight: 600; font-style: italic; font-size: 1.6rem; letter-spacing: -0.01em; color: var(--text); /* Loose enough that italic-Fraunces descenders (g, y, p) and the * breakcore chromatic glow clear the line box — nothing slices them. */ line-height: 1.2; padding-bottom: 0.06em; } .nameplate-subtitle { font-family: var(--font-sans); font-size: 0.65rem; letter-spacing: 0.32em; text-transform: uppercase; color: var(--subtext0); } /* Section ornaments */ .section-rule { display: flex; align-items: center; gap: 1rem; color: var(--subtext0); font-family: var(--font-display); font-style: italic; font-size: 0.95rem; letter-spacing: 0.04em; } .section-rule::before, .section-rule::after { content: ""; flex: 1; height: 1px; background: var(--surface2); } .section-rule .ornament { color: var(--mauve); } /* Scrawled handwritten margin notes */ .scrawl { font-family: var(--font-hand); color: var(--mauve); font-size: 1.4rem; line-height: 1; transform: rotate(-6deg); display: inline-block; } .scrawl-mark::before { content: "✕"; font-family: var(--font-hand); color: var(--red); margin-right: 0.35em; } /* Stripe (Matisse cutout) chip used for tags */ .chip { display: inline-flex; align-items: center; gap: 0.3rem; font-family: var(--font-display); font-style: italic; font-size: 0.78rem; padding: 0.15rem 0.6rem; background: color-mix(in srgb, var(--surface0) 80%, transparent); border: 1px solid var(--surface2); color: var(--subtext1); border-radius: 1px; letter-spacing: 0.02em; } .chip-accent { background: var(--mauve); color: var(--rosewater); border-color: var(--mauve); } .chip-draft { background: color-mix(in srgb, var(--peach) 18%, transparent); color: var(--peach); border-color: color-mix(in srgb, var(--peach) 50%, transparent); } /* Card / glass — keep the name but reinterpret as a paper card */ .glass { background-color: color-mix(in srgb, var(--surface0) 80%, transparent); border: 1px solid var(--surface2); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--surface1) 50%, transparent), 0 10px 30px -20px rgba(20, 16, 12, 0.45); border-radius: 2px; } .salon-noir .glass, .gothic .glass, .breakcore .glass { background-color: color-mix(in srgb, var(--surface0) 70%, transparent); } .salon-noir .glass { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--surface1) 50%, transparent), 0 14px 40px -24px rgba(0, 0, 0, 0.8); } .gothic .glass { border-color: color-mix(in srgb, var(--mauve) 35%, var(--surface2)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mauve) 18%, transparent), 0 14px 40px -24px rgba(0, 0, 0, 0.85); } .breakcore .glass { border-color: color-mix(in srgb, var(--mauve) 45%, var(--surface2)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--mauve) 25%, transparent), 0 0 0 1px color-mix(in srgb, var(--teal) 15%, transparent), 0 14px 40px -24px rgba(0, 0, 0, 0.9); } /* ───── Buttons — one system ───── * Base .btn = layout + size + focus/disabled. One variant for color * (--primary / --ghost / --danger), one size modifier (--sm / --lg), * shape modifiers (--icon / --block). Never restyle buttons ad-hoc. */ .btn { display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem; height: 2.5rem; padding: 0 1.2rem; font-family: var(--font-display); font-style: italic; font-weight: 500; font-size: 0.95rem; line-height: 1; letter-spacing: 0.02em; background: transparent; color: var(--text); border: 1px solid transparent; border-radius: 1px; text-decoration: none; white-space: nowrap; cursor: pointer; transition: transform 0.15s ease, background 0.15s ease, color 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease; } .btn:focus-visible { outline: none; border-color: var(--mauve); box-shadow: 0 0 0 2px color-mix(in srgb, var(--mauve) 35%, transparent); } .btn:disabled, .btn[aria-disabled="true"] { opacity: 0.55; cursor: default; pointer-events: none; } .btn svg { width: 1.05em; height: 1.05em; flex-shrink: 0; } /* Variants */ .btn--primary { background: var(--mauve); color: var(--rosewater); border-color: color-mix(in srgb, var(--mauve) 80%, var(--crust)); box-shadow: 0 1px 2px rgba(0, 0, 0, 0.22); } .btn--primary:hover { transform: translateY(-1px); background: var(--red); border-color: color-mix(in srgb, var(--red) 80%, var(--crust)); box-shadow: 0 7px 16px -7px color-mix(in srgb, var(--red) 65%, transparent); } .btn--primary:active { transform: translateY(0); box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3); } .btn--ghost { color: var(--subtext1); border-color: var(--surface2); background: color-mix(in srgb, var(--surface0) 45%, transparent); } .btn--ghost:hover { color: var(--mauve); border-color: color-mix(in srgb, var(--mauve) 50%, var(--surface2)); background: color-mix(in srgb, var(--surface0) 80%, transparent); } .btn--danger { color: var(--red); border-color: color-mix(in srgb, var(--red) 55%, var(--surface2)); background: color-mix(in srgb, var(--red) 12%, transparent); } .btn--danger:hover { color: var(--rosewater); background: var(--red); border-color: var(--red); } /* Pressed/selected state for toggle & tab buttons */ .btn.is-active { color: var(--mauve); border-color: color-mix(in srgb, var(--mauve) 55%, var(--surface2)); background: color-mix(in srgb, var(--mauve) 14%, transparent); } /* Sizes */ .btn--sm { height: 2rem; padding: 0 0.85rem; font-size: 0.85rem; gap: 0.35rem; } .btn--lg { height: 3rem; padding: 0 1.6rem; font-size: 1.05rem; } /* Shapes */ .btn--icon { padding: 0; width: 2.5rem; } .btn--icon.btn--sm { width: 2rem; } .btn--block { width: 100%; } /* Back-link — a real affordance, not bare body text. One markup for * every "← back" return link (post, admin, login). */ .back-link { display: inline-flex; align-items: center; gap: 0.5rem; font-family: var(--font-display); font-style: italic; font-size: 0.9rem; line-height: 1; color: var(--subtext1); text-decoration: none; padding: 0.35rem 0.1rem; border-bottom: 1px solid color-mix(in srgb, var(--subtext1) 35%, transparent); transition: color 0.15s ease, border-color 0.15s ease, gap 0.15s ease; } .back-link:hover, .back-link:focus-visible { color: var(--mauve); border-color: var(--mauve); gap: 0.7rem; outline: none; } .back-link .bl-arrow { display: inline-block; transition: transform 0.15s ease; } .back-link:hover .bl-arrow, .back-link:focus-visible .bl-arrow { transform: translateX(-3px); } /* ───── Top-bar controls — one height, one language ───── * `.topbar-cluster` lays the chrome controls out as one tidy, right-aligned * group that wraps as a unit (never a ragged full-width column on mobile). * Every control is the same 2rem height; icon-only variants are exact * squares so they line up cleanly next to each other. */ .topbar-cluster { display: flex; align-items: center; flex-wrap: wrap; gap: 0.4rem; justify-content: flex-start; } @media (min-width: 768px) { .topbar-cluster { justify-content: flex-end; } } /* A hairline divider between the public controls and the admin group. */ .topbar-divider { align-self: stretch; width: 1px; margin: 0.15rem 0.15rem; background: var(--surface2); flex: none; } .topbar-control { display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem; height: 2rem; padding: 0 0.7rem; flex: none; font-family: var(--font-display); font-style: italic; font-size: 0.85rem; line-height: 1; color: var(--subtext1); background: color-mix(in srgb, var(--surface0) 55%, transparent); border: 1px solid var(--surface2); border-radius: 1px; text-decoration: none; cursor: pointer; white-space: nowrap; transition: color 0.15s, background 0.15s, border-color 0.15s; } .topbar-control:hover { color: var(--mauve); background: color-mix(in srgb, var(--surface0) 85%, transparent); border-color: color-mix(in srgb, var(--mauve) 45%, var(--surface2)); } .topbar-control:focus-visible { outline: none; border-color: var(--mauve); box-shadow: 0 0 0 2px color-mix(in srgb, var(--mauve) 40%, transparent); } .topbar-control:disabled { opacity: 0.5; cursor: default; } .topbar-control svg { width: 15px; height: 15px; flex-shrink: 0; } /* Exact-square icon-only variant — keeps the row aligned. */ .topbar-control--icon { width: 2rem; padding: 0; } /* Keyboard-shortcut hover/focus tooltip — kept out of the button label, * surfaced only on hover or keyboard focus. */ .kbd-tip-host { position: relative; } .kbd-tip { position: absolute; top: calc(100% + 8px); left: 50%; display: flex; align-items: center; gap: 0.3rem; white-space: nowrap; padding: 4px 8px; font-family: var(--font-sans); font-size: 0.6rem; font-style: normal; letter-spacing: 0.16em; text-transform: uppercase; color: var(--subtext1); background: color-mix(in srgb, var(--crust) 90%, transparent); border: 1px solid color-mix(in srgb, var(--surface2) 70%, transparent); border-radius: 4px; box-shadow: 0 8px 20px -10px rgba(0, 0, 0, 0.5); opacity: 0; transform: translate(-50%, 4px); pointer-events: none; transition: opacity 0.16s ease, transform 0.16s ease; z-index: 60; } .kbd-tip kbd { font-family: var(--font-mono); font-size: 0.62rem; line-height: 1; padding: 2px 5px; color: var(--text); background: color-mix(in srgb, var(--surface0) 70%, transparent); border: 1px solid color-mix(in srgb, var(--surface2) 80%, transparent); border-radius: 3px; } .kbd-tip-host:hover .kbd-tip, .kbd-tip-host:focus-visible .kbd-tip { opacity: 1; transform: translate(-50%, 0); } /* Breakcore: hard neon tooltip — matches the layer's offset-shadow chrome. */ .breakcore .kbd-tip { background: var(--crust); border-color: var(--mauve); border-radius: 0; color: var(--green); box-shadow: 2px 2px 0 var(--mauve); } .breakcore .kbd-tip kbd { color: var(--rosewater); background: var(--surface0); border-color: var(--mauve); border-radius: 0; } @media (prefers-reduced-motion: reduce) { .kbd-tip { transition: opacity 0.16s ease; transform: translate(-50%, 0); } } .topbar-control--danger:hover { color: var(--red); border-color: color-mix(in srgb, var(--red) 55%, var(--surface2)); } /* Native