diff --git a/lexer.mll b/lexer.mll
index 3625d921a2a03984912b62a5063afa0a3f8db1e0..cb5c12637a42a3d7da333b7b467046a8be5a1907 100644
--- a/lexer.mll
+++ b/lexer.mll
@@ -97,10 +97,13 @@ rule token = parse
   | '@' K E Y F R A M E S    { KEYFRAMES_SYM }
   | '@' S U P P O R T S      { SUPPORTS_SYM }
 
+  | (w | comment)* w A N D w (w | comment)* { SUPPORTS_AND }
+  | (w | comment)* w O R w (w | comment)*   { SUPPORTS_OR }
+
   | O N L Y             { ONLY }
   | N O T               { NOT }
   | A N D               { AND }
-  | O R                 { OR }
+  (*| O R                 { OR } removed in favor of SUPPORTS_OR *)
   | F R O M             { FROM }
   | T O                 { TO }
 
diff --git a/parser.mly b/parser.mly
index 5215576f921d37d750e5224e12aadbb4d6fef17c..4cbafc5c69154cf9634efafd4b117e2f44d52109 100644
--- a/parser.mly
+++ b/parser.mly
@@ -53,7 +53,8 @@
 %token <float * string> UNIT_VALUE
 %token <string> COMBINATOR RELATION STRING IDENT HASH URI FUNCTION
 %token LPAREN RPAREN LBRACE RBRACE LBRACK RBRACK SEMICOL COLON COMMA DOT PLUS
-%token MINUS SLASH STAR ONLY AND OR NOT FROM TO EOF
+%token MINUS SLASH STAR ONLY AND (*OR*) NOT FROM TO EOF
+%token SUPPORTS_AND SUPPORTS_OR
 
 (* Start symbol *)
 %type <Types.stylesheet> stylesheet
@@ -62,8 +63,12 @@
 %%
 
 (* list with arbitrary whitespace between elements and separators *)
+%inline ig2(a, b): a b {}
+%inline ig3(a, b, c): a b c {}
 %inline wslist(sep, x): S* l=separated_list(sep, terminated(x, S*))  { l }
-%inline wspreceded(prefix, x): p=preceded(pair(prefix, S*), x) { p }
+%inline wspreceded(prefix, x): p=preceded(ig2(prefix, S*), x) { p }
+
+%inline all_and: AND | SUPPORTS_AND {}
 
 cd: CDO S* | CDC S* {}
 
@@ -112,9 +117,9 @@ media_query_list:
   | S* hd=media_query tl=wspreceded(COMMA, media_query)*
   { hd :: tl }
 media_query:
-  | prefix=only_or_not? typ=media_type S* feat=wspreceded(AND, media_expr)*
+  | prefix=only_or_not? typ=media_type S* feat=wspreceded(all_and, media_expr)*
   { (prefix, Some typ, feat) }
-  | hd=media_expr tl=wspreceded(AND, media_expr)*
+  | hd=media_expr tl=wspreceded(all_and, media_expr)*
   { (None, None, (hd :: tl)) }
 %inline only_or_not:
   | ONLY S*   { "only" }
@@ -171,18 +176,21 @@ supports_negation:
   | NOT S+ c=supports_condition_in_parens
   { Not c }
 supports_conjunction:
-  | hd=supports_condition_in_parens tl=preceded(delimited(S+, AND, S+), supports_condition_in_parens)+
+  | hd=supports_condition_in_parens tl=preceded(SUPPORTS_AND, supports_condition_in_parens)+
   { And (hd :: tl) }
 supports_disjunction:
-  | hd=supports_condition_in_parens tl=preceded(delimited(S+, OR, S+), supports_condition_in_parens)+
+  | hd=supports_condition_in_parens tl=preceded(SUPPORTS_OR, supports_condition_in_parens)+
   { Or (hd :: tl) }
 supports_declaration_condition:
-  | LPAREN S* decl=declaration RPAREN
+  | LPAREN S* decl=supports_declaration RPAREN
   { Decl decl }
+supports_declaration:
+  | name=property S* COLON S* value=expr
+  { (name, value) }
   (*XXX:
 general_enclosed:
   | ( FUNCTION | LPAREN ) ( any | unused )* RPAREN
-  {  }
+  { Enclosed expr }
 
 any:
 [ IDENT | NUMBER | PERCENTAGE | DIMENSION | STRING
@@ -248,7 +256,7 @@ pseudo:
     ":" ^ f ^ "(" ^ arg ^ ")" }
 
 declaration:
-  | name=property S* COLON S* value=expr important=boption(pair(IMPORTANT_SYM, S*))
+  | name=property S* COLON S* value=expr important=boption(ig2(IMPORTANT_SYM, S*))
   { (String.lowercase name, value, important) }
 %inline property: name=IDENT  { name }
 
diff --git a/stringify.ml b/stringify.ml
index 4ee15800d92f7714804b9f30d95fc54e1a34b8c1..b165a599d2237c18ed410931106b29cca502169d 100644
--- a/stringify.ml
+++ b/stringify.ml
@@ -27,8 +27,7 @@ let rec filter_none = function
 let add_parens s =
   let l = String.length s in
   if l > 0 & s.[0] = '(' & s.[l - 1] = ')'
-    then String.sub s 1 (l - 2)
-    else s
+    then s else "(" ^ s ^ ")"
 
 (*
  * Pretty-printing
@@ -76,12 +75,24 @@ let string_of_media_query query =
   | (Some pre, None, _) ->
     failwith "unexpected media query prefix \"" ^ pre ^ "\""
 
-let rec string_of_condition = function
-  | Not c -> "not " ^ add_parens (string_of_condition c)
-  | And c -> cat " and " (add_parens @@ string_of_condition) c
-  | Or c -> cat " or " (add_parens @@ string_of_condition) c
-  | Decl (name, value, false) -> "(" ^ name ^ ": " ^ string_of_expr value ^ ")"
-  | Decl (_, _, true) -> failwith "unexpected \"!important\""
+let stringify_condition w c =
+  let rec transform =
+    let p c = `Parens (transform c) in
+    function
+    | Not c -> `Not (p c)
+    | And c -> `And (List.map p c)
+    | Or c -> `Or (List.map p c)
+    | Decl (name, value) -> `Decl (name, value)
+  in
+  let rec str = function
+    | `Not c -> "not " ^ str c
+    | `And c -> cat " and " str c
+    | `Or c -> cat " or " str c
+    | `Decl (name, value) -> "(" ^ name ^ ":" ^ w ^ string_of_expr value ^ ")"
+    | `Parens (`Decl _ as d) -> str d
+    | `Parens c -> "(" ^ str c ^ ")"
+  in
+  str (transform c)
 
 let block = function "" -> " {}" | body -> " {\n" ^ indent body ^ "\n}"
 
@@ -117,7 +128,7 @@ let rec string_of_statement = function
     in
     "@keyframes " ^ id ^ block (cat "\n\n" string_of_keyframe_ruleset rules)
   | Supports (condition, statements) ->
-    "@supports " ^ string_of_condition condition ^
+    "@supports " ^ stringify_condition " " condition ^
     block (cat "\n\n" string_of_statement statements)
 
 let string_of_stylesheet = cat "\n\n" string_of_statement
@@ -158,10 +169,9 @@ let minify_media_query query =
 
 let rec minify_condition = function
   | Not c -> "not " ^ add_parens (minify_condition c)
-  | And c -> cat "and " (add_parens @@ minify_condition) c
-  | Or c -> cat "or " (add_parens @@ minify_condition) c
-  | Decl (name, value, false) -> "(" ^ name ^ ":" ^ minify_expr value ^ ")"
-  | Decl (_, _, true) -> failwith "unexpected \"!important\""
+  | And c -> cat " and " (add_parens @@ minify_condition) c
+  | Or c -> cat " or " (add_parens @@ minify_condition) c
+  | Decl (name, value) -> "(" ^ name ^ ":" ^ minify_expr value ^ ")"
 
 let rec minify_statement = function
   | Ruleset (selectors, decls) ->
@@ -189,7 +199,7 @@ let rec minify_statement = function
     in
     "@keyframes " ^ id ^ "{" ^ cat "" minify_keyframe_ruleset rules ^ "}"
   | Supports (condition, statements) ->
-    "@supports " ^ minify_condition condition ^
+    "@supports " ^ stringify_condition "" condition ^
     "{" ^ cat "" minify_statement statements ^ "}"
   | statement -> string_of_statement statement
 
diff --git a/types.ml b/types.ml
index 11bd01a3cf7bac6204ee936c8fba9265c72cc808..d986f927cfd240c75692920767b04618fb5e7a91 100644
--- a/types.ml
+++ b/types.ml
@@ -22,11 +22,13 @@ type descriptor_declaration = string * expr
 
 type keyframe_ruleset = expr * declaration list
 
+type supports_declaration = string * expr
+
 type condition =
   | Not of condition
   | And of condition list
   | Or of condition list
-  | Decl of declaration
+  | Decl of supports_declaration
   (*XXX: | Enclosed of expr*)
 
 type statement =