diff --git a/components.css b/components.css new file mode 100644 index 0000000..e8647f2 --- /dev/null +++ b/components.css @@ -0,0 +1,729 @@ +/* ==================================================================== + COMPONENTS — components.css + All reusable UI components. Requires tokens.css loaded first. + ==================================================================== */ + +/* ------------------------------------------------------------------ + 1. TYPOGRAPHY UTILITIES + ------------------------------------------------------------------ */ +.h1, h1 { + font-family: var(--font-heading); + font-size: var(--fs-h1); + font-weight: 700; + line-height: 1.2; + color: var(--fg-default); +} +.h2, h2 { + font-family: var(--font-heading); + font-size: var(--fs-h2); + font-weight: 700; + line-height: 1.25; + color: var(--fg-default); +} +.h3, h3 { + font-family: var(--font-heading); + font-size: var(--fs-h3); + font-weight: 700; + line-height: 1.3; + color: var(--fg-default); +} +.h4, h4 { + font-family: var(--font-heading); + font-size: var(--fs-h4); + font-weight: 500; + line-height: 1.3; + color: var(--fg-default); +} +.p1 { + font-family: var(--font-body); + font-size: var(--fs-p1); + font-weight: 400; + line-height: 1.5; + color: var(--fg-default); +} +.p2 { + font-family: var(--font-body); + font-size: var(--fs-p2); + font-weight: 400; + line-height: 1.5; + color: var(--fg-default); +} +.p3 { + font-family: var(--font-body); + font-size: var(--fs-p3); + font-weight: 400; + line-height: 1.5; + color: var(--fg-default); +} +.caption { + font-family: var(--font-body); + font-size: var(--fs-caption); + font-weight: 400; + line-height: 1.4; + color: var(--fg-default-muted); +} + +/* ------------------------------------------------------------------ + 2. BUTTONS + ------------------------------------------------------------------ */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--padding-xs); + font-family: var(--font-body); + font-size: var(--fs-p3); + font-weight: 600; + border-radius: var(--radii-sm); + padding: 6px var(--padding-sm); + cursor: pointer; + border: none; + transition: background 0.15s var(--ease), + color 0.15s var(--ease), + outline 0.1s var(--ease); + white-space: nowrap; + text-decoration: none; +} + +/* Primary */ +.btn--primary { + background: var(--bg-secondary); + color: var(--fg-default); + border: 4px solid var(--border-default); +} +.btn--primary:hover { + background: var(--bg-tertiary); + border-color: var(--border-default); +} +.btn--primary:active { + background: var(--bg-secondary); + color: var(--fg-default-muted); + border-color: var(--border-default); +} +.btn--primary:focus-visible { + outline: 3px solid var(--fg-blue-darker); + outline-offset: 2px; +} + +/* Secondary (ghost, no border) */ +.btn--secondary { + background: transparent; + color: var(--fg-default-muted); + border: 2px solid transparent; +} +.btn--secondary:hover { + background: rgba(255,255,255,0.06); + color: var(--fg-default); +} +.btn--secondary:active { + background: rgba(255,255,255,0.04); + color: var(--fg-default-muted); +} +.btn--secondary:focus-visible { + outline: 3px solid var(--fg-blue-darker); + outline-offset: 2px; +} + +/* Outlined */ +.btn--outlined { + background: var(--bg-primary); + color: var(--fg-default); + border: 2px solid var(--border-default); +} +.btn--outlined:hover { + background: color-mix(in srgb, var(--bg-primary) 85%, white 15%); +} +.btn--outlined:active { + color: var(--fg-default-muted); +} +.btn--outlined:focus-visible { + outline: 3px solid var(--fg-blue-darker); + outline-offset: 2px; +} + +/* Icon-only button */ +.icon-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + background: transparent; + border: none; + border-radius: var(--radii-xs); + color: var(--fg-default-muted); + cursor: pointer; + flex-shrink: 0; + transition: background 0.15s var(--ease), color 0.15s var(--ease); +} +.icon-btn:hover { background: rgba(255,255,255,0.08); color: var(--fg-default); } +.icon-btn:active { background: rgba(255,255,255,0.04); } +.icon-btn:focus-visible { + outline: 3px solid var(--fg-blue-darker); + outline-offset: 2px; +} +.icon-btn svg { display: block; } + +/* ------------------------------------------------------------------ + 3. DIVIDER + ------------------------------------------------------------------ */ +.form-divider { + border: none; + border-top: 1px solid var(--border-default); + margin: var(--padding-sm) 0; +} + +.form-privacy-note { + display: flex; + align-items: center; + gap: var(--gap-xs); + color: var(--fg-default-muted); + margin: 0; +} + +.form-section--public { + display: flex; + flex-direction: column; + gap: var(--gap-md); +} + +.form-section--private { + display: flex; + flex-direction: column; + gap: var(--gap-md); + background: var(--bg-tertiary); + border-radius: var(--radii-sm); + padding: var(--padding-xs); +} + +/* ------------------------------------------------------------------ + 4. INPUT FIELD COMPONENT + ------------------------------------------------------------------ */ +.input-field { + display: flex; + flex-direction: column; + gap: 4px; + width: 100%; +} + +.input-field__label { + font-family: var(--font-heading); + font-size: var(--fs-h4); + font-weight: 500; + color: var(--fg-default); + line-height: 1.3; +} + +.input-field__caption { + font-family: var(--font-body); + font-size: var(--fs-caption); + font-weight: 400; + color: var(--fg-default-muted); + line-height: 1.4; +} + +/* Wrapper holds icon + input */ +.input-field__wrapper { + position: relative; + width: 100%; +} + +/* Icon positioned inside the wrapper */ +.input-field__icon { + position: absolute; + left: 10px; + top: 50%; + transform: translateY(-50%); + display: flex; + align-items: center; + color: var(--fg-default-muted); + pointer-events: none; + z-index: 1; +} + +/* The actual input / select / textarea */ +.input-field__input { + width: 100%; + height: 36px; + padding: 0 var(--padding-xs); + background: var(--bg-primary); + color: var(--fg-default); + border: 1px solid var(--bg-secondary); + border-radius: var(--radii-xs); + font-family: var(--font-body); + font-size: var(--fs-p3); + font-weight: 400; + appearance: none; + -webkit-appearance: none; + transition: background 0.15s var(--ease), border-color 0.15s var(--ease); + box-sizing: border-box; +} + +/* Icon variant — extra left padding so text doesn't overlap icon */ +.input-field__wrapper--icon .input-field__input { + padding-left: 32px; +} + +/* Active / focus */ +.input-field__input:focus { + outline: none; + background: var(--bg-primary); + border-color: var(--fg-blue-darker); + border-width: 2px; +} +.input-field__input:focus-visible { + outline: none; + border-color: var(--fg-blue-darker); + border-width: 2px; +} + +/* Disabled */ +.input-field__input:disabled { + background: var(--bg-primary); + color: var(--fg-default-muted); + border-color: transparent; + cursor: not-allowed; +} + +/* Error / required-but-empty */ +.input-field__input--error, +.input-field__input--error:focus, +.input-field__input--error:focus-visible { + border-color: var(--fg-red-bright) !important; + border-width: 2px; +} +.input-field--error .input-field__label::after { + content: ' *'; + color: var(--fg-red-bright); +} + +/* Textarea variant */ +.input-field__input--textarea { + height: auto; + min-height: 72px; + padding: var(--padding-xs); + resize: vertical; + line-height: 1.5; +} + +/* Select variant */ +/* ------------------------------------------------------------------ + CUSTOM SELECT DROPDOWN + ------------------------------------------------------------------ */ +.custom-select { + position: relative; +} + +.custom-select__trigger { + /* Button reset — override UA styles */ + -webkit-appearance: none; + appearance: none; + background: var(--bg-primary); + border: 1px solid var(--bg-secondary); + border-radius: var(--radii-xs); + color: var(--fg-default-muted); + font-family: var(--font-body); + font-size: var(--fs-p3); + font-weight: 400; + height: 36px; + padding: 0 var(--padding-xs); + box-sizing: border-box; + /* Layout */ + display: flex; + align-items: center; + justify-content: space-between; + cursor: pointer; + text-align: left; + width: 100%; + transition: background 0.15s var(--ease), border-color 0.15s var(--ease); +} + +.custom-select__trigger .custom-select__value { + color: var(--fg-default-muted); + flex: 1; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.custom-select__trigger.has-value .custom-select__value { + color: var(--fg-default); +} + +.custom-select__icon { + flex-shrink: 0; + margin-left: var(--padding-xs); + color: var(--fg-default-muted); + font-size: 1rem; + transition: transform 0.2s var(--ease); +} + +.custom-select.is-open .custom-select__icon { + transform: rotate(180deg); +} + +.custom-select__list { + position: fixed; /* escapes overflow:hidden on feedback-box */ + z-index: 500; + background: var(--bg-secondary); + border: 4px solid var(--bg-primary); + border-radius: var(--radii-sm); + padding: var(--padding-xs) 0; + margin: 0; + list-style: none; + overflow: hidden; + min-width: 200px; +} + +.custom-select__list[hidden] { display: none; } + +.custom-select__option { + padding: var(--padding-xs) var(--padding-sm); + cursor: pointer; + font-size: var(--text-p3-size); + font-family: var(--text-p3-family); + color: var(--fg-default); + transition: background 0.15s; +} + +.custom-select__option:hover, +.custom-select__option:focus { + background: var(--bg-tertiary); + outline: none; +} + +.custom-select__option[aria-selected="true"] { + color: var(--fg-default); + background: var(--bg-tertiary); +} + +/* ------------------------------------------------------------------ + 4b. Legacy native select (kept for fallback) ← was 4 + ------------------------------------------------------------------ */ +.input-field__input--select { + cursor: pointer; + appearance: none; + -webkit-appearance: none; + padding-right: 2rem; +} + +.input-field__wrapper--select { + position: relative; +} + +.input-field__select-icon { + position: absolute; + right: var(--padding-xs); + top: 50%; + transform: translateY(-50%); + pointer-events: none; + color: var(--fg-default-muted); + font-size: 1rem; +} + +/* Placeholder */ +.input-field__input::placeholder { + color: var(--fg-default-muted); + opacity: 1; +} + +/* ------------------------------------------------------------------ + 5. CONTACT CHIPS + ------------------------------------------------------------------ */ +.contact-chips { + display: flex; + flex-wrap: wrap; + gap: var(--padding-xs); + margin-top: 4px; +} + +.contact-chip { + display: inline-flex; + align-items: center; + gap: var(--gap-xs); + padding: 4px 10px; + background: var(--bg-primary); + color: var(--fg-default-muted); + border: 1px solid var(--border-default); + border-radius: var(--radii-lg); + font-family: var(--font-body); + font-size: var(--fs-p3); + font-weight: 600; + cursor: pointer; + transition: background 0.15s var(--ease), color 0.15s var(--ease), border-color 0.15s var(--ease); + user-select: none; +} + +.contact-chip:hover { + background: var(--bg-secondary); + color: var(--fg-default); +} + +.contact-chip.is-selected { + background: var(--bg-secondary); + color: var(--fg-default); + border-color: var(--fg-default-muted); +} + +.contact-chip:focus-visible { + outline: 3px solid var(--fg-blue-darker); + outline-offset: 2px; +} + +.contact-inputs { + display: flex; + flex-direction: column; + gap: 6px; + margin-top: 6px; +} + +/* Dynamic contact input rows */ +.contact-input-row { + width: 100%; +} + +/* ------------------------------------------------------------------ + 6. FEEDBACK PANEL (SHELL) + ------------------------------------------------------------------ */ +.feedback-panel { + position: fixed; + top: 0; + right: 0; + height: 100vh; + width: var(--panel-w); + display: block; + z-index: 100; + pointer-events: none; +} + +.feedback-panel.is-open { + pointer-events: auto; +} + +/* Single box fills the panel */ +.feedback-box { + position: absolute; + top: var(--padding-md); + right: var(--padding-md); + bottom: var(--padding-md); + left: 0; + display: flex; + flex-direction: column; + background: var(--bg-secondary); + border: 4px solid var(--bg-primary); + border-radius: var(--radii-md); + padding: var(--padding-md); + overflow: hidden; + transform: translateX(calc(100% + var(--padding-md))); + opacity: 0; + transition: transform 0.35s var(--ease), opacity 0.25s var(--ease); +} + +.feedback-panel.is-open .feedback-box:not([hidden]) { + transform: translateX(0); + opacity: 1; +} + +.feedback-box[hidden] { + display: none !important; +} + +#moreVariant { + background: var(--bg-primary); + border-color: var(--bg-secondary); +} + +#viewVariant { + bottom: auto; + min-height: 300px; +} + +/* ── Action Bar ── */ +.actionBar { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: var(--padding-xs) 0; +} + +.actionBar__title-group { + display: flex; + flex-direction: column; + gap: var(--gap-xs); +} + +.actionBar__desc { + color: var(--fg-default-muted); + margin: 0; + flex-shrink: 0; +} + +.actionBar--bordered { + border-bottom: 1px solid var(--bg-tertiary); + margin-bottom: var(--padding-xs); +} + +/* ── Content Bar ── */ +.contentBar { + flex: 1; + overflow-y: auto; + padding: var(--padding-xs) 0 120px; /* extra bottom room so selects open downward */ + display: flex; + flex-direction: column; + gap: var(--padding-sm); + scrollbar-width: thin; + scrollbar-color: var(--bg-tertiary) transparent; +} + +.contentBar::-webkit-scrollbar { + width: 4px; +} +.contentBar::-webkit-scrollbar-thumb { + background: var(--bg-tertiary); + border-radius: 99px; +} + +/* ── Footer Bar ── */ +.footerBar { + display: flex; + align-items: center; + justify-content: flex-end; + gap: 4px; + padding-top: var(--padding-xs); + flex-shrink: 0; + border-top: 1px solid var(--bg-tertiary); + margin-top: var(--padding-xs); +} + +.footerBar--space-between, +.footerBar--between { + justify-content: space-between; +} + +.footerBar--end { + justify-content: flex-end; +} + +/* ── Private label ── */ +.form-private { + display: flex; + align-items: center; + gap: 6px; + padding: var(--padding-xs); + background: rgba(255,255,255,0.04); + border-radius: var(--radii-xs); + color: var(--fg-default-muted); +} + +/* ── View variant fields ── */ +.view-field { + display: flex; + flex-direction: column; + gap: var(--gap-xs); +} + +.view-label { + font-family: var(--font-body); + font-size: var(--fs-caption); + font-weight: 400; + color: var(--fg-default-muted); + line-height: 1.2; +} + +.feedback-quote-box { + border: 1px solid var(--border-default); + border-radius: var(--radii-sm, 6px); + padding: var(--padding-xs); +} + +.rel-chip { + display: inline-block; + width: fit-content; + padding: 2px 8px; + border-radius: var(--radii-sm, 6px); + border: 1px solid; + font-family: var(--font-body); + font-size: var(--fs-p3); + color: var(--fg-default); + line-height: 1.5; +} + +.view-value { + font-family: var(--font-body); + font-size: var(--fs-p1); + color: var(--fg-default); + line-height: 1.5; +} + +/* ── Confirmation variant ── */ +.confirm-title { + font-family: var(--font-heading); + font-size: var(--fs-h2); + font-weight: 700; + color: var(--fg-default); + margin-bottom: var(--padding-xs); +} + +.confirm-desc { + font-family: var(--font-body); + font-size: var(--fs-p2); + color: var(--fg-default-muted); + line-height: 1.6; +} + +/* ── More variant ── */ +.more-section { + display: flex; + flex-direction: column; + gap: var(--padding-xs); +} + +.more-section__body { + font-family: var(--font-body); + font-size: var(--fs-p2); + color: var(--fg-default-muted); + line-height: 1.7; +} + +.more-photos { + display: flex; + flex-wrap: wrap; + gap: var(--padding-sm); + padding-top: var(--padding-xs); + align-items: flex-end; +} + +.more-photo-circle { + border-radius: 50%; + background: var(--bg-tertiary); + flex-shrink: 0; + position: relative; + overflow: hidden; +} +.more-photo-circle img { + width: 100%; + height: 100%; + object-fit: cover; + display: block; + image-orientation: from-image; +} +.more-photo-circle::after { + content: ''; + position: absolute; + inset: 0; + border-radius: 50%; + border: 2px solid rgba(255,255,255,0.08); +} + +/* Scroll hint gradient at bottom of panel */ +.scroll-hint { + position: sticky; + bottom: 0; + height: 32px; + background: linear-gradient(to top, var(--bg-secondary), transparent); + pointer-events: none; + flex-shrink: 0; + margin-top: -32px; +} diff --git a/images/photo1.jpeg b/images/photo1.jpeg new file mode 100644 index 0000000..172432e Binary files /dev/null and b/images/photo1.jpeg differ diff --git a/images/photo2.jpeg b/images/photo2.jpeg new file mode 100644 index 0000000..616bc80 Binary files /dev/null and b/images/photo2.jpeg differ diff --git a/images/photo3.jpeg b/images/photo3.jpeg new file mode 100644 index 0000000..5aa5905 Binary files /dev/null and b/images/photo3.jpeg differ diff --git a/images/photo4.png b/images/photo4.png new file mode 100644 index 0000000..c6b3203 Binary files /dev/null and b/images/photo4.png differ diff --git a/images/photo5.png b/images/photo5.png new file mode 100644 index 0000000..34e27b7 Binary files /dev/null and b/images/photo5.png differ diff --git a/images/photo6.png b/images/photo6.png new file mode 100644 index 0000000..46fc7d5 Binary files /dev/null and b/images/photo6.png differ diff --git a/images/photo7.png b/images/photo7.png new file mode 100644 index 0000000..33cba19 Binary files /dev/null and b/images/photo7.png differ diff --git a/images/photo8.png b/images/photo8.png new file mode 100644 index 0000000..34fd299 Binary files /dev/null and b/images/photo8.png differ diff --git a/images/photo9.png b/images/photo9.png new file mode 100644 index 0000000..d1e9825 Binary files /dev/null and b/images/photo9.png differ diff --git a/index.html b/index.html index eecf626..76f8657 100644 --- a/index.html +++ b/index.html @@ -15,6 +15,12 @@ + + + + + + @@ -30,19 +36,20 @@
-

Golden Github Seeds

+

The people who made GitHub home.

- A garden of hubbers, I had the joy of working and connecting with - while I worked here. Each dot is someone who left a mark on my - experience here. + A field of dots, each one a Hubber who made my time at GitHub worth every moment.

- +
+ + +
@@ -51,89 +58,153 @@

Golden Github Seeds

+ + + + + + + + @@ -209,76 +351,99 @@

Your dot has been planted!

+ diff --git a/style.css b/style.css index f649ad3..def64b8 100644 --- a/style.css +++ b/style.css @@ -1,66 +1,14 @@ /* ==================================================================== - DESIGN TOKENS + LAYOUT — style.css + Page-level layout only. Tokens: tokens.css. Components: components.css. ==================================================================== */ -:root { - /* Foreground */ - --fg-default: #FCFCFC; - --fg-default-muted: #D4D4D4; - - /* Foreground accent (dull) — used for default dot fills */ - --fg-red-dull: #620101; - --fg-yellow-dull: #413803; - --fg-blue-dull: #013B3C; /* teal/blue group */ - --fg-green-dull: #043710; - --fg-purple-dull: #31044B; - - /* Background */ - --bg-primary: #000000; - --bg-secondary: #1F1F1F; - --bg-tertiary: #3D3D3D; - - /* Typography */ - --font-heading: 'Space Mono', 'Courier New', monospace; - --font-body: 'Space Grotesk', system-ui, sans-serif; - - /* Font scale */ - --fs-h1: 28px; - --fs-h2: 24px; - --fs-h3: 20px; - --fs-p1: 18px; - --fs-p2: 16px; - --fs-p3: 14px; - --fs-caption: 12px; - - /* Spacing (padding tokens) */ - --padding-sm: 8px; - --padding-md: 16px; - --padding-lg: 24px; - - /* Radii */ - --radii-sm: 4px; - --radii-md: 12px; - - /* Dot */ - --dot-size: 28px; - - /* Panel */ - --panel-w: clamp(340px, 38vw, 520px); - - /* Animation */ - --ease: cubic-bezier(0.22, 1, 0.36, 1); -} -/* ==================================================================== - RESET - ==================================================================== */ +/* ── Reset ── */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - -html { - -webkit-text-size-adjust: 100%; -} +html { -webkit-text-size-adjust: 100%; background: var(--bg-default); } body { - background: var(--bg-primary); + background: var(--bg-default); color: var(--fg-default); font-family: var(--font-body); font-size: var(--fs-p2); @@ -71,21 +19,10 @@ body { -moz-osx-font-smoothing: grayscale; } -button { font-family: inherit; cursor: pointer; } +button, input, textarea, select { font-family: inherit; } /* ==================================================================== - TYPOGRAPHY UTILITY CLASSES - ==================================================================== */ -.h1 { font-family: var(--font-heading); font-weight: 700; font-size: var(--fs-h1); line-height: 1.15; color: var(--fg-default); } -.h2 { font-family: var(--font-heading); font-weight: 700; font-size: var(--fs-h2); line-height: 1.2; color: var(--fg-default); } -.h3 { font-family: var(--font-heading); font-weight: 700; font-size: var(--fs-h3); line-height: 1.25; color: var(--fg-default); } -.p1 { font-family: var(--font-body); font-weight: 400; font-size: var(--fs-p1); color: var(--fg-default); } -.p2 { font-family: var(--font-body); font-weight: 400; font-size: var(--fs-p2); color: var(--fg-default); } -.p3 { font-family: var(--font-body); font-weight: 400; font-size: var(--fs-p3); color: var(--fg-default); } -.caption { font-family: var(--font-body); font-weight: 400; font-size: var(--fs-caption); color: var(--fg-default-muted); } - -/* ==================================================================== - HOME LAYOUT — three rows that together fill 100vh + HOME LAYOUT — three rows filling 100vh ==================================================================== */ .home { display: flex; @@ -93,35 +30,43 @@ button { font-family: inherit; cursor: pointer; } min-height: 100vh; } -/* ── Dot fields (40vh each) ── */ +/* Dot fields (40vh each) */ .dot-field { position: relative; flex: none; height: 40vh; - background: var(--bg-primary); + background: var(--bg-default); overflow: hidden; } -/* ── Middle content (20vh) ── */ +/* Middle content (20vh) */ .middle-content { - flex: none; - height: 20vh; - display: flex; + flex: none; + height: 20vh; + display: flex; align-items: center; - background: transparent; - padding: 0 var(--padding-lg); - z-index: 1; + background: transparent; + padding: 0 var(--padding-lg); + z-index: 1; } .middle-content__inner { display: flex; flex-direction: column; - gap: var(--padding-md); - max-width: 500px; + gap: var(--padding-sm); + max-width: 520px; +} + +.middle-content__actions { + display: flex; + align-items: center; + gap: var(--padding-xs); + align-self: flex-start; } .middle-content__desc { color: var(--fg-default-muted); + font-family: var(--font-body); font-size: var(--fs-p1); line-height: 1.55; } @@ -137,297 +82,257 @@ button { font-family: inherit; cursor: pointer; } border: none; transform: translate(-50%, -50%); transition: box-shadow 0.25s var(--ease); - /* position set via inline style (left/top %) */ + cursor: default; } -/* Default (dull) fills — no interaction */ -.dot--yellow { background: var(--fg-yellow-dull); pointer-events: none; } -.dot--teal { background: var(--fg-blue-dull); pointer-events: none; } -.dot--green { background: var(--fg-green-dull); pointer-events: none; } -.dot--red { background: var(--fg-red-dull); pointer-events: none; } -.dot--purple { background: var(--fg-purple-dull); pointer-events: none; } +/* Default (dull) — no pointer events */ +.dot--yellow { background: var(--fg-yellow-dull); pointer-events: none; } +.dot--teal { background: var(--fg-blue-dull); pointer-events: none; } +.dot--green { background: var(--fg-green-dull); pointer-events: none; } +.dot--red { background: var(--fg-red-dull); pointer-events: none; } +.dot--purple { background: var(--fg-purple-dull); pointer-events: none; } -/* Submitted — bright gradient + glow, interactive */ +/* Submitted — glowing gradient, interactive */ .dot--submitted.dot--yellow { - background: radial-gradient(circle at 35% 35%, #D4A017, #7A5C00); - box-shadow: 0 0 14px 5px rgba(212,160,23,0.45); + background: radial-gradient(circle at 35% 35%, #D4A017, #7A5C00); + box-shadow: 0 0 14px 5px rgba(212,160,23,0.45); pointer-events: auto; + cursor: pointer; } .dot--submitted.dot--teal { - background: radial-gradient(circle at 35% 35%, #00CCCF, #005557); - box-shadow: 0 0 14px 5px rgba(0,204,207,0.45); + background: radial-gradient(circle at 35% 35%, #00CCCF, #005557); + box-shadow: 0 0 14px 5px rgba(0,204,207,0.45); pointer-events: auto; + cursor: pointer; } .dot--submitted.dot--green { - background: radial-gradient(circle at 35% 35%, #2DBD6A, #0A5C2A); - box-shadow: 0 0 14px 5px rgba(45,189,106,0.4); + background: radial-gradient(circle at 35% 35%, #2DBD6A, #0A5C2A); + box-shadow: 0 0 14px 5px rgba(45,189,106,0.4); pointer-events: auto; + cursor: pointer; } .dot--submitted.dot--red { - background: radial-gradient(circle at 35% 35%, #FF4B4B, #8C0000); - box-shadow: 0 0 14px 5px rgba(255,75,75,0.45); + background: radial-gradient(circle at 35% 35%, #FF4B4B, #8C0000); + box-shadow: 0 0 14px 5px rgba(255,75,75,0.45); pointer-events: auto; + cursor: pointer; } .dot--submitted.dot--purple { - background: radial-gradient(circle at 35% 35%, #B55FFF, #52007A); - box-shadow: 0 0 14px 5px rgba(181,95,255,0.45); + background: radial-gradient(circle at 35% 35%, #B55FFF, #52007A); + box-shadow: 0 0 14px 5px rgba(181,95,255,0.45); pointer-events: auto; + cursor: pointer; } .dot--submitted:hover, .dot--submitted:focus-visible { - box-shadow: 0 0 22px 8px rgba(255,255,255,0.18); + box-shadow: 0 0 24px 10px rgba(255,255,255,0.2); outline: none; } -/* ==================================================================== - BUTTONS - ==================================================================== */ -.btn { - display: inline-flex; - align-items: center; - gap: 8px; - padding: 9px 18px; - border-radius: var(--radii-sm); - font-family: var(--font-heading); - font-weight: 700; - font-size: var(--fs-p3); - line-height: 1; - transition: background 0.2s var(--ease), color 0.2s var(--ease), border-color 0.2s var(--ease); - border: 2px solid transparent; +/* Active — feedback panel open for this dot */ +.dot--active { + outline: 2px solid #fff; + outline-offset: 3px; + box-shadow: 0 0 20px 8px rgba(255,255,255,0.35); } -.btn--primary { - background: var(--bg-tertiary); - color: var(--fg-default); - border-color: var(--bg-tertiary); +/* Dot hover tooltip */ +.dot-tooltip { + position: fixed; + z-index: 200; + display: flex; + flex-direction: column; + gap: 4px; + background: var(--bg-primary); + border: 4px solid #fff; /* overridden inline per color */ + border-radius: var(--radii-sm); + padding: var(--padding-xs) var(--padding-sm); + cursor: pointer; + pointer-events: auto; + white-space: nowrap; + transition: opacity 0.12s ease; } -.btn--primary:hover { background: #4d4d4d; border-color: #4d4d4d; } -.btn--secondary { - background: transparent; - color: var(--fg-default); - border-color: transparent; -} -.btn--secondary:hover { color: var(--fg-default-muted); } +.dot-tooltip[hidden] { display: none !important; } -/* Outlined — used for "Log some words" CTA */ -.btn--outlined { - background: transparent; - color: var(--fg-default); - border-color: var(--bg-tertiary); +.dot-tooltip__name { + color: var(--fg-default); + font-weight: 600; } -.btn--outlined:hover { background: var(--bg-secondary); border-color: var(--fg-default-muted); } -/* Icon button */ -.icon-btn { - display: inline-flex; - align-items: center; - justify-content: center; - background: transparent; - border: none; - color: var(--fg-default); - padding: 4px; - border-radius: var(--radii-sm); - transition: color 0.2s, opacity 0.2s; +.dot-tooltip__role { + color: var(--fg-default-muted); } -.icon-btn:hover { color: var(--fg-default-muted); } -/* ==================================================================== - FEEDBACK PANEL - ==================================================================== */ -.feedback-panel { - position: fixed; - top: var(--padding-lg); - bottom: var(--padding-lg); - right: var(--padding-lg); - width: var(--panel-w); - /* stack children; only one is ever visible at a time */ - display: block; - z-index: 200; - transform: translateX(calc(100% + var(--padding-lg))); - transition: transform 0.35s var(--ease); +/* "This is your dot" callout */ +.your-dot-box { + position: fixed; + z-index: 210; + background: var(--bg-primary); + border: 4px solid var(--bg-secondary); + border-radius: var(--radii-sm); + padding: var(--padding-sm); pointer-events: none; + white-space: nowrap; + color: var(--fg-default); + animation: yourDotFade 3s ease forwards; } +.your-dot-box[hidden] { display: none !important; } -.feedback-panel.is-open { - transform: translateX(0); - pointer-events: all; +@keyframes yourDotFade { + 0% { opacity: 0; transform: translateY(-4px); } + 10% { opacity: 1; transform: translateY(0); } + 80% { opacity: 1; } + 100% { opacity: 0; } } -/* ==================================================================== - FEEDBACK BOX (shared shell) - ==================================================================== */ -.feedback-box { - width: 100%; - height: 100%; - background: var(--bg-secondary); - border: 4px solid var(--bg-tertiary); - border-radius: var(--radii-md); +/* ── Dot search widget ── */ +.dot-search { + position: fixed; + bottom: var(--padding-md); + left: var(--padding-md); + z-index: 150; display: flex; flex-direction: column; - overflow: hidden; -} - -/* hide the [hidden] boxes — belt-and-suspenders */ -.feedback-box[hidden] { display: none !important; } - -/* ── Action Bar ── */ -.actionBar { - flex: none; - display: flex; - align-items: center; - justify-content: space-between; - padding: var(--padding-sm) var(--padding-md); -} - -.actionBar--bordered { - border-bottom: 2px solid var(--bg-tertiary); + gap: 4px; + background: var(--bg-default); + border: 4px solid var(--bg-secondary); + border-radius: var(--radii-sm); + padding: var(--padding-xs) var(--padding-sm) var(--padding-sm); + min-width: 220px; } -.actionBar--end { justify-content: flex-end; } - -/* ── Content Bar ── */ -.contentBar { - flex: 1; - overflow-y: auto; - padding: var(--padding-md); - display: flex; - flex-direction: column; - gap: var(--padding-md); - scrollbar-width: thin; - scrollbar-color: var(--bg-tertiary) transparent; +.dot-search__label { + color: var(--fg-default-muted); + font-size: var(--text-caption-size); + font-family: var(--text-caption-family); + user-select: none; } -.contentBar::-webkit-scrollbar { width: 4px; } -.contentBar::-webkit-scrollbar-track { background: transparent; } -.contentBar::-webkit-scrollbar-thumb { background: var(--bg-tertiary); border-radius: 2px; } - -/* ── Footer Bar ── */ -.footerBar { - flex: none; - display: flex; +.dot-search__input-wrapper { + position: relative; + display: flex; align-items: center; - padding: var(--padding-sm) var(--padding-md); } -.footerBar--end { justify-content: flex-end; } -.footerBar--between { justify-content: space-between; } -.footerBar--gap { gap: 4px; } - -/* ── Scroll hint ── */ -.scroll-hint { - text-align: right; - padding: 0 var(--padding-md) 4px; - cursor: pointer; - user-select: none; +.dot-search__icon { + position: absolute; + left: var(--padding-xs); color: var(--fg-default-muted); - letter-spacing: 0.04em; - flex: none; -} -.scroll-hint:hover { color: var(--fg-default); } - -/* ==================================================================== - FORM ELEMENTS (Edit variant) - ==================================================================== */ -.form-group { - display: flex; - flex-direction: column; - gap: 4px; + pointer-events: none; + flex-shrink: 0; } -.form-label { color: var(--fg-default); } -.form-hint { color: var(--fg-default-muted); font-size: var(--fs-caption); font-family: var(--font-body); } - -.form-input, -.form-select, -.form-textarea { - background: var(--bg-tertiary); +.dot-search__input { + background: var(--bg-default); border: 1.5px solid var(--bg-tertiary); - border-radius: var(--radii-sm); + border-radius: var(--radii-xs); + padding: var(--padding-xs) var(--padding-sm); + padding-left: calc(var(--padding-xs) + 14px + 8px); color: var(--fg-default); - font-family: var(--font-body); - font-size: var(--fs-p3); - padding: 7px 10px; + font-size: var(--text-p3-size); + font-family: var(--text-p3-family); + width: 100%; outline: none; - transition: border-color 0.2s; - /* short inputs match the image width */ - width: min(180px, 55%); -} - -.form-textarea { - width: 100%; - resize: vertical; - min-height: 100px; + box-sizing: border-box; } - -.form-input:focus, -.form-select:focus, -.form-textarea:focus { - border-color: var(--fg-default-muted); -} - -.form-select { - cursor: pointer; - -webkit-appearance: none; - appearance: none; -} - -.form-private { - color: var(--fg-default-muted); - font-size: var(--fs-caption); - font-family: var(--font-body); - margin-top: var(--padding-sm); +.dot-search__input:focus { + border-color: var(--fg-default); + background: var(--bg-primary); } +.dot-search__input::placeholder { color: var(--fg-default-muted); } +/* hide browser ✕ on type=search */ +.dot-search__input::-webkit-search-cancel-button { display: none; } -/* ==================================================================== - VIEW VARIANT - ==================================================================== */ -.view-field { - display: flex; - flex-direction: column; - gap: 6px; +/* Inactive state — shown while feedback panel is open */ +.dot-search--inactive { + opacity: 0.45; + pointer-events: none; } - -.view-label { color: var(--fg-default); } -.view-value { color: var(--fg-default-muted); font-size: var(--fs-p1); line-height: 1.55; } - -/* ==================================================================== - CONFIRMATION VARIANT - ==================================================================== */ -.confirm-desc { - color: var(--fg-default-muted); - line-height: 1.6; +.dot-search--inactive .dot-search__label, +.dot-search--inactive .dot-search__icon, +.dot-search--inactive .dot-search__input, +.dot-search--inactive .dot-search__input::placeholder { + color: var(--fg-default-muted); } /* ==================================================================== RESPONSIVE ==================================================================== */ @media (max-width: 860px) { - /* Stack panel to bottom sheet on narrow screens */ - .feedback-panel { - top: auto; - right: 0; - bottom: 0; - left: 0; - width: 100%; - height: 88vh; - padding: var(--padding-md); - transform: translateY(100%); - display: block; + .middle-content { + padding: 0 var(--padding-md); + height: auto; + min-height: 20vh; } + .middle-content__inner { max-width: 100%; } - .feedback-panel.is-open { transform: translateY(0); } - - .middle-content { padding: 0 var(--padding-md); } + /* Panel becomes bottom sheet */ + .feedback-panel { + top: auto !important; + right: 0 !important; + bottom: 0 !important; + left: 0 !important; + width: 100% !important; + height: 88vh !important; + transform: translateY(100%) !important; + } + .feedback-panel.is-open { transform: translateY(0) !important; } - .middle-content__inner { max-width: 100%; } + .feedback-box { + top: 0; + right: 0; + bottom: 0; + left: 0; + } } @media (max-width: 480px) { - :root { --dot-size: 22px; } + :root { --dot-size: 20px; } + .h1 { font-size: 22px; } + .middle-content { padding: var(--padding-md); } +} + +/* ==================================================================== + REALLY NARROW — panel flows below bottomContent + ==================================================================== */ +@media (max-width: 420px) { + /* Pull the panel out of fixed-stacking and let it flow in the document */ + .feedback-panel { + position: relative !important; + top: auto !important; + right: auto !important; + bottom: auto !important; + left: auto !important; + width: 100% !important; + height: auto !important; + /* Hide via max-height collapse; no translateY needed */ + max-height: 0 !important; + overflow: hidden !important; + transform: none !important; + transition: max-height 0.4s var(--ease), opacity 0.3s var(--ease) !important; + opacity: 0 !important; + } - .h1 { font-size: 22px; } + .feedback-panel.is-open { + max-height: 1400px !important; + opacity: 1 !important; + transform: none !important; + } - .middle-content { height: auto; min-height: 20vh; padding: var(--padding-md); } + /* Feedback box fills its parent width, no absolute positioning */ + .feedback-box { + position: relative !important; + top: auto !important; + right: auto !important; + bottom: auto !important; + left: auto !important; + width: 100% !important; + min-height: 300px; + box-sizing: border-box; + transform: none !important; + opacity: 1 !important; + margin: var(--padding-md) 0 !important; + } } diff --git a/tokens.css b/tokens.css new file mode 100644 index 0000000..df99291 --- /dev/null +++ b/tokens.css @@ -0,0 +1,80 @@ +/* ==================================================================== + DESIGN TOKENS — tokens.css + Source of truth for all design decisions. + ==================================================================== */ +:root { + /* ── Foreground ── */ + --fg-default: #FCFCFC; + --fg-default-muted: #D4D4D4; + --fg-inverse: #1E1E1E; + --fg-inverse-muted: #404040; + + /* Semantic foreground — darker (text/icon) + muted (tint) per hue */ + --fg-red-darker: #D71111; + --fg-red-muted: #FFE2E0; + --fg-orange-darker: #946A00; + --fg-orange-muted: #FFEC9E; + --fg-blue-darker: #006EDB; + --fg-blue-muted: #D1F0FF; + --fg-purple-darker: #894CEB; + --fg-purple-muted: #F1E5FF; + --fg-green-darker: #2C8141; + --fg-green-muted: #CAF7CA; + + /* Dull fills — default (unsubmitted) dot state */ + --fg-red-dull: #620101; + --fg-yellow-dull: #413803; + --fg-blue-dull: #013B3C; + --fg-green-dull: #043710; + --fg-purple-dull: #31044B; + + /* Bright error red */ + --fg-red-bright: #FF4444; + + /* ── Background ── */ + --bg-default: #171717; + --bg-primary: #232323; + --bg-secondary: #3C3C3C; + --bg-tertiary: #3D3D3D; + --bg-inverse: #E6E6E6; + + /* ── Border ── */ + --border-default: #494949; + + /* ── Typography ── */ + --font-heading: 'Space Mono', 'Courier New', monospace; + --font-body: 'Space Grotesk', system-ui, sans-serif; + + --fs-h1: 28px; + --fs-h2: 24px; + --fs-h3: 20px; + --fs-h4: 18px; + --fs-p1: 18px; + --fs-p2: 16px; + --fs-p3: 14px; + --fs-caption: 12px; + + /* ── Spacing ── */ + --padding-xs: 8px; + --padding-sm: 16px; + --padding-md: 24px; + --padding-lg: 40px; + --padding-xl: 60px; + + /* Gap scale */ + --gap-xs: 4px; + --gap-sm: 8px; + --gap-md: 16px; + --gap-lg: 32px; + + /* ── Radii ── */ + --radii-xs: 4px; + --radii-sm: 8px; + --radii-md: 12px; + --radii-lg: 16px; + + /* ── Misc ── */ + --dot-size: 28px; + --panel-w: clamp(340px, 38vw, 520px); + --ease: cubic-bezier(0.22, 1, 0.36, 1); +}