@font-face { font-family: 'Iosevka Patrick'; src: url('/static/fonts/IosevkaPatrickNerdFont-Regular.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap; } @font-face { font-family: 'Iosevka Patrick'; src: url('/static/fonts/IosevkaPatrickNerdFont-Medium.woff2') format('woff2'); font-weight: 500; font-style: normal; font-display: swap; } @font-face { font-family: 'Iosevka Patrick'; src: url('/static/fonts/IosevkaPatrickNerdFont-SemiBold.woff2') format('woff2'); font-weight: 600; font-style: normal; font-display: swap; } /* ======================================== Texture Patterns (inline SVG noise) ======================================== */ /* Corkboard — organic, fine-grained, warm */ :root { --texture-cork: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='c'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='5' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0.3 0 0 0 0.15 0.2 0 0 0 0.08 0.1 0 0 0 0.02 0 0 0 0.15 0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23c)'/%3E%3C/svg%3E"); /* Feed board — warm cork brown */ --feed-board-bg: #C4A882; --feed-board-border: #B09470; /* Sticky note base — warm off-white */ --feed-card-bg: #FFFDF5; /* Dot-grid + kraft — defined once per theme, theme blocks just swap the active alias */ --texture-dotgrid-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Ccircle cx='10' cy='10' r='0.7' fill='%23d2bab0' fill-opacity='0.35'/%3E%3C/svg%3E"); --texture-dotgrid-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20'%3E%3Ccircle cx='10' cy='10' r='0.7' fill='%235A4A40' fill-opacity='0.4'/%3E%3C/svg%3E"); --texture-kraft-light: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Cfilter id='k'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0.15 0 0 0 0.1 0.1 0 0 0 0.06 0.05 0 0 0 0.02 0 0 0 0.07 0'/%3E%3C/filter%3E%3Crect width='150' height='150' filter='url(%23k)'/%3E%3C/svg%3E"); --texture-kraft-dark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='150' height='150'%3E%3Cfilter id='k'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.65' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0.08 0 0 0 0.04 0.06 0 0 0 0.03 0.03 0 0 0 0.01 0 0 0 0.06 0'/%3E%3C/filter%3E%3Crect width='150' height='150' filter='url(%23k)'/%3E%3C/svg%3E"); --texture-dotgrid: var(--texture-dotgrid-light); --texture-kraft: var(--texture-kraft-light); /* Journal paper — warm cream */ --journal-bg: #FFFDF5; /* Kraft — slightly warmer/darker than card bg */ --kraft-bg: #F7F0E8; } /* ======================================== Design Tokens (CSS Custom Properties) Light theme (default) ======================================== */ :root { /* Page */ --page-bg: #FAF7F5; --page-text: #3d2319; /* Cards */ --card-bg: #FFFFFF; --card-border: #eaddd7; --card-shadow: rgba(61, 35, 25, 0.06); --card-shadow-hover: rgba(61, 35, 25, 0.10); /* Surfaces (inset areas inside cards) */ --surface-bg: rgba(250, 247, 245, 0.5); --surface-border: #f2e8e5; /* Header */ --header-bg-from: #4a2c2a; --header-bg-to: #3d2319; --header-border: #7f5539; --header-text: #FAF7F5; /* Text hierarchy */ --text-primary: #3d2319; --text-secondary: #4a2c2a; --text-muted: #7f5539; --text-faint: #bfa094; --text-placeholder: #d2bab0; /* Interactive */ --btn-primary-bg: #4a2c2a; --btn-primary-bg-hover: #3d2319; --btn-primary-text: #FAF7F5; --btn-secondary-bg: #FFFFFF; --btn-secondary-border: #e0cec7; --btn-secondary-text: #6b4423; --btn-secondary-bg-hover: #FAF7F5; /* Forms */ --input-bg: #FFFFFF; --input-border: #e0cec7; --input-border-focus: #7f5539; --input-ring-focus: rgba(127, 85, 57, 0.15); --input-bg-focus: rgba(250, 247, 245, 0.3); /* Tables */ --table-bg: #FFFFFF; --table-header-bg: #FAF7F5; --table-border: #eaddd7; --table-row-hover: #FAF7F5; --table-divider: #f2e8e5; /* Modals */ --modal-bg: #FFFFFF; --modal-border: #eaddd7; --modal-backdrop: rgba(0, 0, 0, 0.4); /* Feed type indicators (filter pills + type badges) */ --type-brew: #6b4423; --type-bean: #b45309; --type-recipe: #a0522d; --type-roaster: #92400e; --type-grinder: #78716c; --type-brewer: #5b6e4e; /* Type background tints */ --type-brew-tint: rgba(107, 68, 35, 0.14); --type-bean-tint: rgba(180, 83, 9, 0.12); --type-recipe-tint: rgba(160, 82, 45, 0.12); --type-roaster-tint: rgba(146, 64, 14, 0.12); --type-grinder-tint: rgba(120, 113, 108, 0.10); --type-brewer-tint: rgba(91, 110, 78, 0.12); /* Rating badges */ --rating-bg: #fef3c7; --rating-text: #78350f; /* Status text — danger / success */ --text-danger: #b91c1c; --text-success: #15803d; /* Alerts/warnings */ --alert-warning-bg: #fffbeb; --alert-warning-border: #fbbf24; --alert-warning-text: #78350f; --alert-warning-text-muted: #92400e; /* Shadows */ --shadow-sm: 0 1px 3px var(--card-shadow); --shadow-md: 0 4px 12px var(--card-shadow-hover); --shadow-lg: 0 10px 25px var(--card-shadow-hover); /* Footer */ --footer-bg: #FAF7F5; --footer-border: #eaddd7; } /* ======================================== Dark theme Activates via: OS preference OR data-theme="dark" on data-theme="light" forces light even on dark OS ======================================== */ @media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { /* Page */ --page-bg: #0F0A08; --page-text: #FAF7F5; /* Cards */ --card-bg: #1C1210; --card-border: #2E211B; --card-shadow: rgba(0, 0, 0, 0.3); --card-shadow-hover: rgba(0, 0, 0, 0.4); /* Surfaces (inset areas inside cards) */ --surface-bg: rgba(36, 26, 22, 0.6); --surface-border: #2E211B; /* Journal/label page backgrounds */ --texture-dotgrid: var(--texture-dotgrid-dark); --texture-kraft: var(--texture-kraft-dark); --journal-bg: #1A1210; --kraft-bg: #201814; /* Feed board — noticeably lighter than cards for contrast */ --feed-board-bg: #3D2D22; --feed-board-border: #4A3828; /* Sticky notes — dark, sitting on the lighter board */ --feed-card-bg: #1A1210; /* Header */ --header-bg-from: #0F0A08; --header-bg-to: #0F0A08; --header-border: #2E211B; --header-text: #FAF7F5; /* Text hierarchy */ --text-primary: #FAF7F5; --text-secondary: #E0CEC4; --text-muted: #C4A898; --text-faint: #8B7265; --text-placeholder: #5A4A40; /* Interactive */ --btn-primary-bg: #7f5539; --btn-primary-bg-hover: #6b4423; --btn-primary-text: #FAF7F5; --btn-secondary-bg: #241A16; --btn-secondary-border: #3D2D24; --btn-secondary-text: #E0CEC4; --btn-secondary-bg-hover: #2E211B; /* Forms */ --input-bg: #241A16; --input-border: #3D2D24; --input-border-focus: #fbbf24; --input-ring-focus: rgba(251, 191, 36, 0.15); --input-bg-focus: rgba(36, 26, 22, 0.8); /* Tables */ --table-bg: #1C1210; --table-header-bg: #241A16; --table-border: #2E211B; --table-row-hover: #241A16; --table-divider: #241A16; /* Modals */ --modal-bg: #1C1210; --modal-border: #2E211B; --modal-backdrop: rgba(0, 0, 0, 0.6); /* Feed type indicators - brighter on dark */ --type-brew: #a67c52; --type-bean: #d97706; --type-recipe: #c4724a; --type-roaster: #c2610e; --type-grinder: #a8a29e; --type-brewer: #8ba37a; /* Type background tints */ --type-brew-tint: rgba(166, 124, 82, 0.18); --type-bean-tint: rgba(217, 119, 6, 0.15); --type-recipe-tint: rgba(196, 114, 74, 0.15); --type-roaster-tint: rgba(194, 97, 14, 0.15); --type-grinder-tint: rgba(168, 162, 158, 0.12); --type-brewer-tint: rgba(139, 163, 122, 0.15); /* Rating badges */ --rating-bg: rgba(251, 191, 36, 0.15); --rating-text: #fbbf24; /* Status text — danger / success */ --text-danger: #fca5a5; --text-success: #86efac; /* Alerts/warnings */ --alert-warning-bg: rgba(251, 191, 36, 0.08); --alert-warning-border: rgba(251, 191, 36, 0.3); --alert-warning-text: #fde68a; --alert-warning-text-muted: #fcd34d; /* Shadows - darker, less visible on dark bg */ --shadow-sm: 0 1px 3px var(--card-shadow); --shadow-md: 0 4px 12px var(--card-shadow-hover); --shadow-lg: 0 10px 25px var(--card-shadow-hover); /* Footer */ --footer-bg: #0F0A08; --footer-border: #2E211B; } /* Override common hardcoded Tailwind classes for dark mode */ .text-brown-900 { color: var(--text-primary) !important; } .text-brown-800 { color: var(--text-primary) !important; } .text-brown-700 { color: var(--text-secondary) !important; } .text-brown-600 { color: var(--text-muted) !important; } .text-brown-500 { color: var(--text-faint) !important; } .text-brown-400 { color: var(--text-placeholder) !important; } .bg-brown-50 { background-color: var(--page-bg) !important; } .bg-brown-100 { background-color: var(--surface-bg) !important; } .bg-brown-200 { background-color: var(--card-border) !important; } .bg-brown-300 { background-color: var(--surface-bg) !important; } .border-brown-200 { border-color: var(--card-border) !important; } .border-brown-300 { border-color: var(--card-border) !important; } .bg-white { background-color: var(--card-bg) !important; } .bg-white\/60 { background-color: var(--surface-bg) !important; } /* Amber badges stay visible on dark */ .bg-amber-50 { background-color: rgba(251, 191, 36, 0.1); } .bg-amber-100 { background-color: rgba(251, 191, 36, 0.15); } .bg-amber-400 { background-color: #fbbf24; } .text-amber-900 { color: #fde68a; } .text-amber-700 { color: #fcd34d; } .text-amber-600 { color: #fbbf24; } .border-amber-400 { border-color: rgba(251, 191, 36, 0.4); } /* Warning/alert backgrounds */ .bg-green-50 { background-color: rgba(251, 191, 36, 0.08) !important; } /* Hover states */ .hover\:bg-brown-200:hover { background-color: var(--surface-bg) !important; } .hover\:bg-brown-100:hover { background-color: var(--surface-bg) !important; } .hover\:bg-brown-50:hover { background-color: var(--surface-bg) !important; } .hover\:text-brown-900:hover { color: var(--text-primary) !important; } .hover\:text-brown-800:hover { color: var(--text-primary) !important; } .hover\:text-brown-700:hover { color: var(--text-secondary) !important; } /* Dividers */ .divide-brown-200 > :not([hidden]) ~ :not([hidden]) { border-color: var(--card-border) !important; } .divide-brown-300 > :not([hidden]) ~ :not([hidden]) { border-color: var(--card-border) !important; } /* Ring colors for avatars */ .ring-brown-500 { --tw-ring-color: #3D2D24 !important; } .hover\:ring-brown-400:hover { --tw-ring-color: #5A4A40 !important; } /* Opacity-variant backgrounds (used in recipe stats grid, etc.) */ .bg-brown-50\/60 { background-color: var(--surface-bg) !important; } .bg-brown-200\/60 { background-color: var(--card-border) !important; } .border-brown-200\/60 { border-color: var(--card-border) !important; } /* Group hover text (used in recipe author links) */ .group-hover\/author\:text-brown-900:hover, .group\/author:hover .group-hover\/author\:text-brown-900 { color: var(--text-primary) !important; } .group-hover\/author\:text-brown-800:hover, .group\/author:hover .group-hover\/author\:text-brown-800 { color: var(--text-primary) !important; } /* Forker avatar borders */ .border-white { border-color: var(--card-bg) !important; } /* Decoration colors */ .decoration-brown-300 { text-decoration-color: var(--card-border) !important; } .hover\:decoration-brown-500:hover { text-decoration-color: var(--text-faint) !important; } } /* Manual dark theme override (data-theme="dark" on ) */ :root[data-theme="dark"] { --page-bg: #0F0A08; --page-text: #FAF7F5; --card-bg: #1C1210; --card-border: #2E211B; --card-shadow: rgba(0, 0, 0, 0.3); --card-shadow-hover: rgba(0, 0, 0, 0.4); --surface-bg: rgba(36, 26, 22, 0.6); --surface-border: #2E211B; --feed-board-bg: #3D2D22; --feed-board-border: #4A3828; --feed-card-bg: #1A1210; --texture-dotgrid: var(--texture-dotgrid-dark); --texture-kraft: var(--texture-kraft-dark); --journal-bg: #1A1210; --kraft-bg: #201814; --header-bg-from: #0F0A08; --header-bg-to: #0F0A08; --header-border: #2E211B; --header-text: #FAF7F5; --text-primary: #FAF7F5; --text-secondary: #E0CEC4; --text-muted: #C4A898; --text-faint: #8B7265; --text-placeholder: #5A4A40; --btn-primary-bg: #7f5539; --btn-primary-bg-hover: #6b4423; --btn-primary-text: #FAF7F5; --btn-secondary-bg: #241A16; --btn-secondary-border: #3D2D24; --btn-secondary-text: #E0CEC4; --btn-secondary-bg-hover: #2E211B; --input-bg: #241A16; --input-border: #3D2D24; --input-border-focus: #fbbf24; --input-ring-focus: rgba(251, 191, 36, 0.15); --input-bg-focus: rgba(36, 26, 22, 0.8); --table-bg: #1C1210; --table-header-bg: #241A16; --table-border: #2E211B; --table-row-hover: #241A16; --table-divider: #241A16; --modal-bg: #1C1210; --modal-border: #2E211B; --modal-backdrop: rgba(0, 0, 0, 0.6); --type-brew: #a67c52; --type-bean: #d97706; --type-recipe: #c4724a; --type-roaster: #c2610e; --type-grinder: #a8a29e; --type-brewer: #8ba37a; --type-brew-tint: rgba(166, 124, 82, 0.18); --type-bean-tint: rgba(217, 119, 6, 0.15); --type-recipe-tint: rgba(196, 114, 74, 0.15); --type-roaster-tint: rgba(194, 97, 14, 0.15); --type-grinder-tint: rgba(168, 162, 158, 0.12); --type-brewer-tint: rgba(139, 163, 122, 0.15); --rating-bg: rgba(251, 191, 36, 0.15); --rating-text: #fbbf24; --text-danger: #fca5a5; --text-success: #86efac; --alert-warning-bg: rgba(251, 191, 36, 0.08); --alert-warning-border: rgba(251, 191, 36, 0.3); --alert-warning-text: #fde68a; --alert-warning-text-muted: #fcd34d; --shadow-sm: 0 1px 3px var(--card-shadow); --shadow-md: 0 4px 12px var(--card-shadow-hover); --shadow-lg: 0 10px 25px var(--card-shadow-hover); --footer-bg: #0F0A08; --footer-border: #2E211B; } /* Tailwind class overrides for dark theme (both auto and manual) */ :root[data-theme="dark"] .text-brown-900, :root[data-theme="dark"] .text-brown-800 { color: var(--text-primary) !important; } :root[data-theme="dark"] .text-brown-700 { color: var(--text-secondary) !important; } :root[data-theme="dark"] .text-brown-600 { color: var(--text-muted) !important; } :root[data-theme="dark"] .text-brown-500 { color: var(--text-faint) !important; } :root[data-theme="dark"] .text-brown-400 { color: var(--text-placeholder) !important; } :root[data-theme="dark"] .bg-brown-50 { background-color: var(--page-bg) !important; } :root[data-theme="dark"] .bg-brown-100 { background-color: var(--surface-bg) !important; } :root[data-theme="dark"] .bg-brown-200 { background-color: var(--card-border) !important; } :root[data-theme="dark"] .bg-brown-300 { background-color: var(--surface-bg) !important; } :root[data-theme="dark"] .border-brown-200, :root[data-theme="dark"] .border-brown-300 { border-color: var(--card-border) !important; } :root[data-theme="dark"] .bg-white { background-color: var(--card-bg) !important; } :root[data-theme="dark"] .bg-white\/60 { background-color: var(--surface-bg) !important; } :root[data-theme="dark"] .bg-amber-50 { background-color: rgba(251, 191, 36, 0.1); } :root[data-theme="dark"] .bg-amber-100 { background-color: rgba(251, 191, 36, 0.15); } :root[data-theme="dark"] .text-amber-900 { color: #fde68a; } :root[data-theme="dark"] .text-amber-700 { color: #fcd34d; } :root[data-theme="dark"] .text-amber-600 { color: #fbbf24; } :root[data-theme="dark"] .border-amber-400 { border-color: rgba(251, 191, 36, 0.4); } :root[data-theme="dark"] .bg-green-50 { background-color: rgba(251, 191, 36, 0.08) !important; } :root[data-theme="dark"] .hover\:bg-brown-200:hover, :root[data-theme="dark"] .hover\:bg-brown-100:hover, :root[data-theme="dark"] .hover\:bg-brown-50:hover { background-color: var(--surface-bg) !important; } :root[data-theme="dark"] .hover\:text-brown-900:hover, :root[data-theme="dark"] .hover\:text-brown-800:hover { color: var(--text-primary) !important; } :root[data-theme="dark"] .hover\:text-brown-700:hover { color: var(--text-secondary) !important; } :root[data-theme="dark"] .divide-brown-200 > :not([hidden]) ~ :not([hidden]), :root[data-theme="dark"] .divide-brown-300 > :not([hidden]) ~ :not([hidden]) { border-color: var(--card-border) !important; } :root[data-theme="dark"] .ring-brown-500 { --tw-ring-color: #3D2D24 !important; } :root[data-theme="dark"] .hover\:ring-brown-400:hover { --tw-ring-color: #5A4A40 !important; } :root[data-theme="dark"] .bg-brown-50\/60 { background-color: var(--surface-bg) !important; } :root[data-theme="dark"] .bg-brown-200\/60 { background-color: var(--card-border) !important; } :root[data-theme="dark"] .border-brown-200\/60 { border-color: var(--card-border) !important; } :root[data-theme="dark"] .border-white { border-color: var(--card-bg) !important; } :root[data-theme="dark"] .decoration-brown-300 { text-decoration-color: var(--card-border) !important; } :root[data-theme="dark"] .hover\:decoration-brown-500:hover { text-decoration-color: var(--text-faint) !important; } @tailwind base; @tailwind components; @tailwind utilities; @layer base { h1, h2, h3 { @apply font-semibold; } /* Touch targets for interactive elements only */ button, input[type="submit"], input[type="button"] { min-height: 44px; min-width: 44px; } /* Filter pills opt out of the 44px touch target */ [class*="filter-pill"] { min-height: auto; min-width: auto; } /* Global keyboard focus ring — visible only for keyboard users (not click) */ :focus-visible { outline: 2px solid var(--input-border-focus); outline-offset: 2px; border-radius: 2px; } /* Clear native outline when focus-visible is in play (we draw our own above) */ :focus:not(:focus-visible) { outline: none; } /* Prevent iOS zoom on input focus */ @media (max-width: 768px) { input, select, textarea { font-size: 16px; } } } @layer components { /* Page Containers */ .page-container { @apply mx-auto px-2 sm:px-4; } .page-container-sm { @apply page-container max-w-2xl; } .page-container-md { @apply page-container max-w-3xl; } .page-container-lg { @apply page-container max-w-4xl; } .page-container-xl { @apply page-container max-w-6xl; } /* Cards and Containers */ .card { background: var(--card-bg); border: 1px solid var(--card-border); @apply rounded-xl; box-shadow: var(--shadow-sm); transition: box-shadow 200ms ease; } .card:hover { box-shadow: var(--shadow-md); } .card-inner { @apply p-6; } .card-sm { background: var(--card-bg); border: 1px solid var(--card-border); @apply rounded-lg; box-shadow: var(--shadow-sm); } /* Section box for lighter content areas */ .section-box { background: var(--surface-bg); @apply rounded-lg p-4; } /* Record view — tinted header region */ .record-view-header { @apply -mx-6 -mt-6 px-6 pt-5 pb-4 mb-6 rounded-t-xl; border-bottom: 1px solid var(--surface-border); } .record-view-header-brew { background: linear-gradient(to bottom, var(--type-brew-tint), transparent); } .record-view-header-bean { background: linear-gradient(to bottom, var(--type-bean-tint), transparent); } .record-view-header-recipe { background: linear-gradient(to bottom, var(--type-recipe-tint), transparent); } .record-view-header-roaster { background: linear-gradient(to bottom, var(--type-roaster-tint), transparent); } .record-view-header-grinder { background: linear-gradient(to bottom, var(--type-grinder-tint), transparent); } .record-view-header-brewer { background: linear-gradient(to bottom, var(--type-brewer-tint), transparent); } /* Record view — author line */ .record-view-author { @apply flex items-center gap-3 mb-4; } .record-view-author-info { @apply flex-1 min-w-0; } .record-view-author-names { @apply flex items-center gap-2 flex-wrap; } .record-view-author-displayname { @apply font-semibold truncate; color: var(--text-primary); } .record-view-author-handle { @apply text-sm truncate; color: var(--text-muted); } .record-view-author-handle:hover { color: var(--text-secondary); } .record-view-meta { @apply flex items-center gap-3 text-sm; color: var(--text-muted); } /* Record view — title area */ .record-view-title { @apply text-2xl font-bold tracking-tight; color: var(--text-primary); } .record-view-timestamp { @apply text-sm mt-1; color: var(--text-muted); } /* ── Shared record view tokens ── */ .detail-label { @apply text-xs font-medium uppercase tracking-wider; color: var(--text-muted); } .detail-value { @apply font-semibold; color: var(--text-primary); } .detail-value-lg { @apply font-bold text-lg; color: var(--text-primary); } .detail-value a { color: var(--text-primary); } .detail-value a:hover { text-decoration: underline; } .detail-stacked { @apply flex flex-col gap-1; } .detail-inline { @apply flex items-baseline gap-2; } .record-view-footer { @apply flex flex-wrap justify-between items-center gap-3 pt-4 mt-6; } .record-stat-line { @apply flex items-center gap-3 text-xs pt-3; color: var(--text-muted); } .brew-rating-hero { @apply inline-flex items-baseline gap-1.5 py-1; } /* Bean hero header: title/byline on the left, rating fills empty space on the right. Wraps the rating to a new line on narrow screens. */ .bean-hero-row { @apply flex flex-wrap items-end justify-between gap-x-6 gap-y-3; } .bean-hero-text { @apply min-w-0; flex: 1 1 auto; } .bean-hero-row .brew-rating-hero { @apply flex-shrink-0; } .brew-summary { @apply flex flex-wrap items-center gap-x-8 gap-y-4 mb-6 pb-5; border-bottom: 1px solid var(--surface-border); } .brew-summary-stats { @apply flex flex-wrap gap-x-6 gap-y-3; flex: 1 1 auto; } .brew-summary-stat { @apply flex flex-col gap-0.5; } .brew-summary-stat dt { @apply uppercase tracking-wider; font-size: 0.65rem; color: var(--text-muted); } .brew-summary-stat dd { @apply text-base font-semibold; color: var(--text-primary); font-variant-numeric: tabular-nums; } .brew-rating-value { @apply font-bold tracking-tight leading-none; font-size: clamp(3.25rem, 6vw + 1rem, 4.5rem); color: var(--rating-text); /* Trim the line-box to the cap/alphabetic edges so the big number sits flush against the "/ 10" baseline without phantom leading whitespace. Progressive enhancement — older browsers ignore these. */ text-box: trim-both cap alphabetic; } .brew-rating-max { @apply text-xs font-medium uppercase tracking-wider; color: var(--text-muted); } /* ── Treatment 1: Brew Journal ── Dot-grid paper, ledger-style fields, for brews/recipes/equipment */ .record-journal { background-color: var(--journal-bg); background-image: var(--texture-dotgrid); @apply rounded-lg; } /* Ledger field: label left, value right, separated by faint line */ .journal-field { @apply flex items-baseline justify-between py-3; border-bottom: 1px solid var(--surface-border); } .journal-field:last-child { border-bottom: none; } .journal-field .detail-label { @apply flex-shrink-0; width: 9rem; } .journal-field .detail-value, .journal-field .detail-value-lg { @apply text-right flex-1; } .journal-field a.detail-value { @apply text-right; } /* On mobile, stack journal fields vertically */ @media (max-width: 480px) { .journal-field { @apply flex-col items-start gap-1; } .journal-field .detail-value, .journal-field .detail-value-lg { @apply text-left; } } /* Section heading inside the journal ledger — separates Inputs/Process/Output */ .ledger-section { @apply text-xs font-semibold uppercase mt-7 mb-1 pb-1; letter-spacing: 0.18em; color: var(--text-muted); border-bottom: 1px solid var(--surface-border); } .ledger-section:first-child { @apply mt-0; } /* Kraft tape chip — used for recipe fork provenance */ .fork-chip { @apply inline-flex items-center gap-1 text-xs font-medium px-3 py-1 mb-5; background-color: var(--kraft-bg); background-image: var(--texture-kraft); color: var(--text-secondary); border: 1px solid var(--surface-border); border-radius: 2px; transform: rotate(-1.25deg); box-shadow: var(--shadow-sm); } .fork-chip a { color: var(--text-primary); text-decoration: underline; text-decoration-color: var(--text-faint); text-underline-offset: 2px; } .fork-chip a:hover { text-decoration-color: var(--text-muted); } /* Pour rows: shared by brew and recipe views */ .pour-row { @apply flex gap-4 text-sm py-2; border-bottom: 1px solid var(--surface-border); } .pour-row:last-child { border-bottom: none; } /* Prose section in journal context */ .journal-prose { @apply whitespace-pre-wrap leading-relaxed; color: var(--text-primary); } /* Bean reference inside a journal brew page */ .journal-bean-ref { @apply rounded-lg p-4 mb-2; background: var(--surface-bg); transition: background 0.15s ease; } .journal-bean-ref:hover { background: var(--type-bean-tint); } /* ── Treatment 2: Craft Label ── Kraft paper texture, bold typographic hierarchy, for beans/roasters */ .record-label { background-color: var(--kraft-bg); background-image: var(--texture-kraft); @apply rounded-lg; } /* Origin hero — the biggest element on a bean label */ .label-origin-hero { @apply text-3xl sm:text-4xl font-bold tracking-tight leading-tight; color: var(--text-primary); } /* Roaster byline under bean name */ .label-byline { @apply text-sm mt-1; color: var(--text-muted); } .label-byline a { color: var(--text-secondary); } .label-byline a:hover { text-decoration: underline; color: var(--text-primary); } /* Inline tag strip: variety / process / roast level — stamp marks, not pills */ .label-tags { @apply flex flex-wrap gap-x-3 gap-y-2 mt-5; } .label-tag { @apply text-[0.7rem] font-semibold uppercase px-2.5 py-1; letter-spacing: 0.14em; background: transparent; color: var(--text-secondary); border: 1px solid var(--text-muted); border-radius: 2px; } .label-tag-closed { color: var(--text-muted); border-color: var(--text-faint); border-style: dashed; } /* Category-tinted label tags — muted, earthy hues that fit the palette. Use bg + border + text together so each pill reads as one tone. */ .label-tag-origin { background: #eef0e8; border-color: #b6c0a6; color: #4a5a3a; } .label-tag-variety { background: #efe5ec; border-color: #b89aae; color: #5c3a52; } .label-tag-process { background: #e7ebef; border-color: #a4b1bd; color: #3e4a57; } /* Roast level — graduated amber/brown by darkness */ .label-tag-roast-1 { background: #fdf3dc; border-color: #e6c97a; color: #6b4f1a; } .label-tag-roast-2 { background: #f7e6c2; border-color: #d4a85a; color: #5a3d10; } .label-tag-roast-3 { background: #ebd2a4; border-color: #b88947; color: #4a2f0c; } .label-tag-roast-4 { background: #d9b483; border-color: #8a6332; color: #3a2408; } .label-tag-roast-5 { background: #b8895a; border-color: #5e3f1c; color: #2a1604; } .label-tag-roast-6 { background: #6b4423; border-color: #2a1604; color: #fdf3dc; } /* Description on a label — flowing paragraph, no indent */ .label-description { @apply leading-relaxed mt-6; color: var(--text-primary); max-width: 65ch; } /* Stacked detail for label pages (location, website) */ .label-detail { @apply flex flex-col gap-1 py-3; border-bottom: 1px solid var(--surface-border); } .label-detail:last-child { border-bottom: none; } /* Form field groups — semantic clusters within modals */ .form-fieldset { @apply space-y-3; } .form-fieldset-label { @apply text-xs font-medium uppercase tracking-wider mb-1; color: var(--text-muted); } .form-divider { border-top: 1px solid var(--surface-border); @apply my-2; } .form-optional-hint { @apply text-xs; color: var(--text-faint); } /* Form validation errors */ .form-error { @apply text-xs mt-1 block; color: #b91c1c; } :root[data-theme="dark"] .form-error, .dark .form-error { color: #fca5a5; } .form-input-error { border-color: #b91c1c; } .form-input-error:focus { border-color: #b91c1c; box-shadow: 0 0 0 2px rgba(185, 28, 28, 0.15); } /* Buttons */ .btn { @apply inline-flex items-center justify-center px-4 py-2 rounded-lg font-medium transition-colors cursor-pointer; } .btn-primary { @apply btn text-white; background: var(--btn-primary-bg); } .btn-primary:hover { background: var(--btn-primary-bg-hover); } .btn-secondary { @apply btn; background: var(--btn-secondary-bg); color: var(--btn-secondary-text); border: 1px solid var(--btn-secondary-border); } .btn-secondary:hover { background: var(--btn-secondary-bg-hover); } .btn-tertiary { @apply btn text-white; background: var(--btn-primary-bg); } .btn-tertiary:hover { background: var(--btn-primary-bg-hover); } .btn-link { color: var(--text-muted); @apply font-medium underline transition-colors cursor-pointer; } .btn-link:hover { color: var(--text-primary); } .btn-danger { @apply text-red-600 hover:text-red-800 font-medium underline transition-colors cursor-pointer; } /* Forms */ .form-label { @apply block text-sm font-medium mb-2; color: var(--text-primary); } .form-input { @apply rounded-lg text-base py-2 px-3; background: var(--input-bg); border: 1px solid var(--input-border); color: var(--text-primary); transition: border-color 150ms ease, box-shadow 150ms ease, background-color 150ms ease; } .form-input:focus { border-color: var(--input-border-focus); box-shadow: 0 0 0 2px var(--input-ring-focus); background: var(--input-bg-focus); outline: none; } /* Hide number input spinners */ input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } input[type="number"] { -moz-appearance: textfield; } .form-input::placeholder { color: var(--text-placeholder); } /* Select/option dark mode fix — native