diff --git a/components.css b/components.css new file mode 100644 index 0000000..78a4bdb --- /dev/null +++ b/components.css @@ -0,0 +1,740 @@ +/* ==================================================================== + 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; +} + +/* Required asterisk — always visible on required fields */ +.input-field:has(:required) .input-field__label::after { + content: '*'; + color: var(--fg-red-bright); + margin-left: 2px; + font-size: 0.65em; + vertical-align: super; +} + +/* Suppress browser default red border on :invalid required fields */ +.input-field__input:invalid { + box-shadow: none; + border-color: var(--bg-secondary); +} + +/* Error / required-but-empty (JS-driven only) */ +.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; +} + +/* 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(--border-default); + 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 9ded366..0e0146d 100644 --- a/index.html +++ b/index.html @@ -4,145 +4,956 @@ - Devyani Jain — Product Designer - + Golden Github Seeds — Devyani Jain + - - - - - - - - - - - - - - - + - + + + + + + + -
- -
+ + +
+ + +
+ + + + + + + + + diff --git a/style.css b/style.css index cbe60ac..def64b8 100644 --- a/style.css +++ b/style.css @@ -1,373 +1,338 @@ -/* ------------------------------------------------------------------ * - * Devyani Jain — portfolio - * Original design. Framed "card UI" layout with a sticky identity - * column and scrollable work, warm off-white palette, pill accents. - * Inspired in spirit by minimal typographic + framed-card portfolios; - * all code original. - * ------------------------------------------------------------------ */ - -:root { - /* Color — warm, soft, light */ - --bg: #ece8e1; - --surface: #f7f5f1; - --surface-2: #fffdfa; - --text: #1b1a18; - --muted: #7a756c; - --line: #e4dfd6; - --accent: #e0553a; - --accent-soft: #f3d9d0; - - /* Type */ - --font: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, - Arial, sans-serif; - - /* Shape & motion */ - --radius-frame: 26px; - --radius-card: 20px; - --radius-pill: 999px; - --ease: cubic-bezier(0.22, 1, 0.36, 1); - - /* Spacing */ - --gap: 10px; - --pad: clamp(1.5rem, 3.2vw, 3rem); -} +/* ==================================================================== + LAYOUT — style.css + Page-level layout only. Tokens: tokens.css. Components: components.css. + ==================================================================== */ -*, -*::before, -*::after { - box-sizing: border-box; -} - -html { - scroll-behavior: smooth; - -webkit-text-size-adjust: 100%; -} +/* ── Reset ── */ +*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } +html { -webkit-text-size-adjust: 100%; background: var(--bg-default); } body { - margin: 0; - padding: var(--gap); - min-height: 100vh; - background: var(--bg); - color: var(--text); - font-family: var(--font); - font-size: clamp(1rem, 0.96rem + 0.25vw, 1.0625rem); - line-height: 1.6; - letter-spacing: -0.01em; - -webkit-font-smoothing: antialiased; + background: var(--bg-default); + color: var(--fg-default); + font-family: var(--font-body); + font-size: var(--fs-p2); + line-height: 1.5; + min-height: 100vh; + overflow-x: hidden; + -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } -h1, -h2, -p { - margin: 0; -} - -a { - color: inherit; - text-decoration: none; -} - -/* ----------------------------- Frame ------------------------------ */ - -.frame { - display: grid; - grid-template-columns: minmax(360px, 460px) 1fr; - gap: var(--gap); - align-items: start; -} - -.panel { - background: var(--surface); - border-radius: var(--radius-frame); - padding: var(--pad); -} +button, input, textarea, select { font-family: inherit; } -/* Left column sticks; right column scrolls with the page */ -.panel--intro { - position: sticky; - top: var(--gap); - height: calc(100vh - var(--gap) * 2); - display: flex; +/* ==================================================================== + HOME LAYOUT — three rows filling 100vh + ==================================================================== */ +.home { + display: flex; flex-direction: column; - justify-content: space-between; - gap: 2rem; - overflow: hidden; + min-height: 100vh; } -.panel--work { - display: flex; - flex-direction: column; - gap: var(--gap); - min-height: calc(100vh - var(--gap) * 2); - background: transparent; - padding: 0; +/* Dot fields (40vh each) */ +.dot-field { + position: relative; + flex: none; + height: 40vh; + background: var(--bg-default); + overflow: hidden; } -/* ------------------------------ Pills ----------------------------- */ - -.pill { - display: inline-flex; +/* Middle content (20vh) */ +.middle-content { + flex: none; + height: 20vh; + display: flex; align-items: center; - gap: 0.45rem; - padding: 0.5rem 0.9rem; - border-radius: var(--radius-pill); - background: var(--surface-2); - border: 1px solid var(--line); - font-size: 0.875rem; - font-weight: 500; - color: var(--text); - line-height: 1; - transition: background 0.25s var(--ease), color 0.25s var(--ease), - border-color 0.25s var(--ease), transform 0.25s var(--ease); -} - -.pill__dot { - width: 7px; - height: 7px; - border-radius: 50%; - background: var(--accent); - flex: none; -} - -.pill__arrow { - transition: transform 0.25s var(--ease); + background: transparent; + padding: 0 var(--padding-lg); + z-index: 1; } -/* ---------------------------- Brand / nav ------------------------- */ - -.panel__top { - display: flex; - align-items: center; - justify-content: space-between; - gap: 1rem; - flex-wrap: wrap; +.middle-content__inner { + display: flex; + flex-direction: column; + gap: var(--padding-sm); + max-width: 520px; } -.brand { - display: inline-flex; +.middle-content__actions { + display: flex; align-items: center; - gap: 0.5rem; - font-weight: 600; - letter-spacing: -0.02em; -} - -.brand__mark { - color: var(--accent); - font-size: 1.1em; -} - -.nav { - display: flex; - gap: 0.4rem; - flex-wrap: wrap; + gap: var(--padding-xs); + align-self: flex-start; } -.nav__item { - background: var(--surface-2); +.middle-content__desc { + color: var(--fg-default-muted); + font-family: var(--font-body); + font-size: var(--fs-p1); + line-height: 1.55; } -.nav__item:hover, -.nav__item:focus-visible { - background: var(--text); - color: var(--surface); - border-color: var(--text); -} - -/* ----------------------------- Intro ------------------------------ */ - -.panel__body { - display: flex; +/* ==================================================================== + DOTS + ==================================================================== */ +.dot { + position: absolute; + width: var(--dot-size); + height: var(--dot-size); + border-radius: 50%; + border: none; + transform: translate(-50%, -50%); + transition: box-shadow 0.25s var(--ease); + cursor: default; +} + +/* 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 — 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); + 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); + 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); + 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); + 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); + pointer-events: auto; + cursor: pointer; +} + +.dot--submitted:hover, +.dot--submitted:focus-visible { + box-shadow: 0 0 24px 10px rgba(255,255,255,0.2); + outline: none; +} + +/* 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); +} + +/* Dot hover tooltip */ +.dot-tooltip { + position: fixed; + z-index: 200; + display: flex; flex-direction: column; - gap: 1.5rem; + 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; } -.eyebrow { - font-size: 0.8125rem; - font-weight: 500; - letter-spacing: 0.08em; - text-transform: uppercase; - color: var(--accent); -} +.dot-tooltip[hidden] { display: none !important; } -.intro { - font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.35rem); - line-height: 1.18; +.dot-tooltip__name { + color: var(--fg-default); font-weight: 600; - letter-spacing: -0.03em; -} - -.intro__muted { - color: var(--muted); -} - -/* --------------------------- Contact ------------------------------ */ - -.panel__foot { - display: flex; - flex-direction: column; - gap: 0.9rem; -} - -.foot__label { - font-size: 0.8125rem; - font-weight: 500; - letter-spacing: 0.06em; - text-transform: uppercase; - color: var(--muted); -} - -.pill-row { - display: flex; - flex-wrap: wrap; - gap: 0.5rem; -} - -.pill--link:hover, -.pill--link:focus-visible { - background: var(--accent); - color: #fff; - border-color: var(--accent); - transform: translateY(-1px); -} - -.pill--link:hover .pill__dot { - background: #fff; -} - -.pill--link:hover .pill__arrow { - transform: translate(2px, -2px); -} - -/* ------------------------------ Work ------------------------------ */ - -.work__head { - padding: 0.25rem 0.25rem 0; -} - -.pill--label { - background: var(--surface); -} - -.card { - background: var(--surface); - border-radius: var(--radius-card); - padding: var(--pad); - transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease); } -.card:hover { - transform: translateY(-3px); - box-shadow: 0 18px 40px -24px rgba(27, 26, 24, 0.35); +.dot-tooltip__role { + color: var(--fg-default-muted); } -.card__head { - display: flex; - flex-wrap: wrap; - align-items: center; - justify-content: space-between; - gap: 0.75rem; - margin-bottom: 1.1rem; +/* "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; } -.card__title { - font-size: clamp(1.4rem, 1.05rem + 1.4vw, 2rem); - font-weight: 600; - letter-spacing: -0.025em; - line-height: 1.15; +@keyframes yourDotFade { + 0% { opacity: 0; transform: translateY(-4px); } + 10% { opacity: 1; transform: translateY(0); } + 80% { opacity: 1; } + 100% { opacity: 0; } } -.pill--meta { - background: var(--surface-2); - color: var(--muted); - white-space: nowrap; - font-weight: 500; +/* ── Dot search widget ── */ +.dot-search { + position: fixed; + bottom: var(--padding-md); + left: var(--padding-md); + z-index: 150; + display: flex; + flex-direction: column; + 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; } -.card__desc { - color: var(--muted); - max-width: 62ch; - font-size: clamp(1rem, 0.97rem + 0.2vw, 1.0625rem); +.dot-search__label { + color: var(--fg-default-muted); + font-size: var(--text-caption-size); + font-family: var(--text-caption-family); + user-select: none; } -/* ---------------------------- Work foot --------------------------- */ - -.work__foot { - margin-top: auto; - display: flex; - flex-wrap: wrap; +.dot-search__input-wrapper { + position: relative; + display: flex; align-items: center; - justify-content: space-between; - gap: 1rem; - padding: 1.25rem var(--pad); - color: var(--muted); - font-size: 0.9375rem; -} - -.foot__top { - transition: color 0.25s var(--ease); -} - -.foot__top:hover, -.foot__top:focus-visible { - color: var(--text); } -/* --------------------------- Fade-in ------------------------------ * - * Cards are visible by default. Where supported, they fade + rise as - * they scroll into view. Fully progressive; respects reduced motion. - * ------------------------------------------------------------------ */ - -@media (prefers-reduced-motion: no-preference) { - @supports (animation-timeline: view()) { - .fade-in { - animation: fade-rise linear both; - animation-timeline: view(); - animation-range: entry 0% cover 20%; - } +.dot-search__icon { + position: absolute; + left: var(--padding-xs); + color: var(--fg-default-muted); + pointer-events: none; + flex-shrink: 0; +} + +.dot-search__input { + background: var(--bg-default); + border: 1.5px solid var(--bg-tertiary); + 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-size: var(--text-p3-size); + font-family: var(--text-p3-family); + width: 100%; + outline: none; + box-sizing: border-box; +} +.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; } + +/* Inactive state — shown while feedback panel is open */ +.dot-search--inactive { + opacity: 0.45; + pointer-events: none; +} +.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) { + .middle-content { + padding: 0 var(--padding-md); + height: auto; + min-height: 20vh; } -} - -@keyframes fade-rise { - from { - opacity: 0; - transform: translateY(26px); - } - to { - opacity: 1; - transform: translateY(0); - } -} - -/* --------------------------- Responsive --------------------------- */ - -@media (max-width: 900px) { - .frame { - grid-template-columns: 1fr; - } - - .panel--intro { - position: static; - height: auto; - min-height: min(88vh, 640px); + .middle-content__inner { max-width: 100%; } + + /* 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; } - .panel--work { - min-height: 0; + .feedback-box { + top: 0; + right: 0; + bottom: 0; + left: 0; } } -@media (max-width: 520px) { - :root { - --pad: 1.4rem; +@media (max-width: 480px) { + :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; } - .panel__top { - align-items: flex-start; + .feedback-panel.is-open { + max-height: 1400px !important; + opacity: 1 !important; + transform: none !important; } - .card__head { - flex-direction: column; - align-items: flex-start; + /* 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); +}